#include "Duplicate.h"
#include "Common/TableData/MapMapCfg.h"
#include "Scene/SceneMgr.h"
#include "Duplicate/brush/BrushMonsMgr.h"
#include "Common/TableDataEx/DuplicateCfg.h"
#include "Script/ScriptMgr.h"
#include "DuplicateMgr.h"
#include "Duplicate/cond/CondMgr.h"
#include "Character/monster/MonsterRefCfg.h"
#include "Common/TableData/AreaAreaCfg.h"
#include "Character/drop/DropMgr.h"
#include "Common/Item/ItemMgr.h"
#include "Common/MailDefine.h"
#include "base/core/Utf8AndWideChar.h"
#include "Mail/GMailManager.h"
#include "Character/CreatureMgr.h"
#include "Common/TableDataEx/MapCfg.h"
#include "Common/Utility/AccountUtility.h"
#include "Character/newAI/behaviac/CreatureCommonAI.h"
#include "Common/CampDefine.h"
#include "Character/PlayerMgr.h"
#include "Common/UnionDefine.h"
#include "Common/TableData/MonsterMonsterCfg.h"

Duplicate::Duplicate() :m_nDuplicateID(0), 
	m_pDuplicateCfg(nullptr),
	m_pVecCondition(nullptr),
	m_pMapStar(nullptr),
	m_pScene(nullptr),
	m_nStartTime(0),
	m_nStartBrushTime(0),
	m_nReadyStartTime(0),
	m_bFinishBrush(false),
	m_bReadyTimeOut(false),
	m_bEnd(false),
	m_bNotifyEnd(false),
	m_nResult(0),
	m_towerCid(0),
	m_byType((int8_t)EDuplicateType::EDuplicateType_None),
	m_nSceneID(0),
	m_nMapID(0),
	m_pBrushMonster(nullptr),
	m_pCond(nullptr),
	m_monsterNum(0),
	m_reliveSec(DUP_RELIVE_SEC)
	
	
{
	
	m_setPlayer.clear();
	m_setMonster.clear();
	m_setNpc.clear();
	m_mapKillNum.clear();
	m_mapDieNum.clear();
	m_mapAllDieMonter.clear();
	m_paramEx.clear();
	m_mapPlayerRelive.clear();
	m_mapReliveNum.clear();
	m_setOnceEnter.clear();
	m_setReward.clear();
	m_mapPlayerOuput.clear();
	m_mapPlayerBear.clear();
	m_setRobot.clear();
	m_mapExploit.clear();
	m_setBornMonster.clear();
	m_mapAllTypeMonster.clear();
	m_mapAllMonster.clear();
	m_mapGroupMons.clear();
}

Duplicate::~Duplicate()
{

}

//初始化副本状态
void Duplicate::InitDuplicateState()
{
	int8_t i = (int8_t)EDuplicateState::EDuplicateState_None + 1;
	for (; i < (int8_t)EDuplicateState::EDuplicateState_Limit; ++i)
	{
		AddDuplicateState(i);
	}
}

//初始化
bool Duplicate::Init(uint32_t nDuplicateID, uint32_t nSceneID, IBrushMonster *pBrush)
{
	if (nullptr == pBrush)
	{
		LogErrFmtPrint("[logic] Duplicate::Init...nullptr == pBrush  duplicateid:%u ", nDuplicateID);
		return false;
	}
	const DuplicateDuplicateCfgInfo *pCfg = g_GetDuplicateDuplicateCfgTable()->GetDuplicateDuplicateCfgInfo(nDuplicateID);
	if (nullptr == pCfg)
	{
		LogErrFmtPrint("[logic] Duplicate::Init...nullptr == pCfg  duplicateid:%u ", nDuplicateID);
		return false;
	}
	m_pVecCondition = g_GetDuplicateCfgMgr()->GetDulicateCondtionCfg(nDuplicateID);
	if (nullptr == m_pVecCondition)
	{
		LogErrFmtPrint("[logic] Duplicate::Init...nullptr == m_pVecCondition  duplicateid:%u ", nDuplicateID);
		return false;
	}
	if (m_pVecCondition->size() < 1)
	{
		LogErrFmtPrint("[logic] Duplicate::Init...m_pVecCondition->size() < 1  duplicateid : %u ", nDuplicateID);
		return false;
	}
	//这里的场景ID暂时用地图ID，后面需要场景管理那边分配
	m_pScene = g_GetSceneMgr()->GetScene(nSceneID);
	if (nullptr == m_pScene)
	{
		LogErrFmtPrint("[logic] Duplicate::Init... GetScene failed...sceneid:%u ", nSceneID);
		return false;
	}
	int8_t itype = m_pVecCondition->at(0);
	if (itype <= (int8_t)EDupCondType::EDupCondType_None
		|| itype >= (int8_t)EDupCondType::EDupCondType_Limit
		)
	{
		LogErrFmtPrint("[logic] Duplicate::Init...m_pVecCondition itype error... duplicateid : %u, itype:%d ", nDuplicateID,itype);
		return false;
	}
	//
	ICond *pCond = g_GetCondMgr()->MakeCondObj(itype);
	if (nullptr == pCond)
	{
		LogErrFmtPrint("[logic] Duplicate::Init...nullptr == pCond... duplicateid : %u, itype:%d ", nDuplicateID, itype);
		return false;
	}
	//
	m_pDuplicateCfg = pCfg;
	m_nDuplicateID = nDuplicateID;
	m_nSceneID = m_pScene->GetSceneId();
	m_nMapID = m_pScene->GetMapId();
	m_nStartTime = Time::Now().sec();
	//
	const MapMapCfgInfo *pMapCfg = g_GetMapMapCfgTable()->GetMapMapCfgInfo(m_nMapID);
	if (nullptr != pMapCfg)
	{
		m_reliveSec = pMapCfg->reviveTime;//设置一次复活时间
	}
	else
	{
		LogWarningFmtPrint("[logic] Duplicate::Init...can not find map cfg....dupid:%u, sceneid:%u,mapid:%u ",m_nDuplicateID,m_nSceneID,m_nMapID);
	}
	//
	if (!pCond->init(this, m_pVecCondition, pCfg->mstType))
	{
		LogErrFmtPrint("[logic] Duplicate::Init...pCond->init return false... duplicateid : %u, itype:%d ", nDuplicateID, itype);
		g_GetCondMgr()->FreeCondObj(pCond);
		//m_dupStar.uninit();
		return false;
	}
	//设置条件
	m_pCond = pCond;
	//设置刷怪指针
	m_pBrushMonster = pBrush;

	//初始化脚本
	if (!InitScript())
	{
		MMOLOG_FMT_ERROR("[logic] Duplicate::Init....InitScript failed....duplicateid:%u, m_nSceneID:%u  ", nDuplicateID, m_nSceneID);
		g_GetCondMgr()->FreeCondObj(pCond);
		m_pCond = nullptr;
		//m_pBrushMonster 在外层有释放，这里不要回收了		
		return false;
	}
	//初始化刷怪，要放到初始化脚本之后
	m_pBrushMonster->Init(this);
	//获取一次场景里所有怪物
	m_pScene->GetAllMonsterInScene(m_setMonster);

	//初始化状态
	InitDuplicateState();
	//设置准备状态
	if (!SetDuplicateState((int8_t)EDuplicateState::EDuplicateState_Ready))
	{
		MMOLOG_FMT_ERROR("[logic] Duplicate::Init....SetDuplicateState failed....duplicateid:%u ", nDuplicateID);
	}
	m_nReadyStartTime = g_GetGlobalServerTime()->UnixSec();
	//设置更新定时器
	if (!g_GetTimerAxis()->SetTimer(ETimer_Update, 1000 * 1, this))
	{
		MMOLOG_FMT_ERROR("[logic] Duplicate::Init....SetTimer failed....duplicateid:%u ", nDuplicateID);
	}

	//初始化副本订阅事件
	InitCommonEvent();	
	//添加怪物出生
	AddBornMonster(m_setMonster);
	//初始化所有类型怪
	InitAllTypeMonster();
	return true;
}

//
void Duplicate::UnInit()
{
	//通知中心服销毁副本
	g_GetDuplicateMgr()->DuplicateDestoryRsp(m_nSceneID);


	killAllFixTimer(this);
	killAllTimer(this);

	g_GetEvent()->UnSubscribeAll(this);

	//在清理一次玩家
	SET_UINT64 setPlayer = m_setPlayer;
	SET_UINT64::iterator iterPlayer = setPlayer.begin();
	for (; iterPlayer != setPlayer.end(); ++iterPlayer)
	{
		CharIDType charId = (*iterPlayer);
		Player *pPlayer = GetPlayer(charId);
		if (nullptr != pPlayer)
		{
			LogDebugFmtPrint("[logic] Duplicate::UnInit....clean player.....dupid:%u, sceneid:%u, mapid:%u, cid:%lu ", m_nDuplicateID, m_nSceneID, m_nMapID, charId);
			if (RET_SUCCESS != LeaveDuplicate(pPlayer))
			{
				LogErrFmtPrint("[logic] Duplicate::UnInit....LeaveDuplicate failed....duplicateid:%u, sceneid:%u, mapid:%u, dup_type:%d, cid%u", m_nDuplicateID,m_nSceneID , m_nMapID,m_byType, pPlayer->GetCid());
			}
		}
	}

	if (nullptr != m_pScene)
	{
		g_GetSceneMgr()->DestoryScene(m_pScene->GetSceneId());
	}
	if (nullptr != m_pBrushMonster)
	{
		g_GetBrushMonsMgr()->RecycleBrush(m_pBrushMonster);
	}
	if (nullptr != m_pCond)
	{
		g_GetCondMgr()->RecycleCond(m_pCond);
	}
	

	//
	m_dupStar.uninit();
	m_dupBlock.UnInit();


	m_setPlayer.clear();
	m_setMonster.clear();
	m_setNpc.clear();
	m_mapKillNum.clear();
	m_mapDieNum.clear();
	m_mapAllDieMonter.clear();

	m_pDuplicateCfg = nullptr;
	m_pVecCondition = nullptr;
	m_pScene = nullptr;
	m_pBrushMonster = nullptr;
	m_bFinishBrush = false;
	m_bEnd = false;
	m_bReadyTimeOut = false;
	m_paramEx.clear();
	m_mapPlayerRelive.clear();
	m_mapReliveNum.clear();
	m_monsterNum = 0;
	m_setOnceEnter.clear();
	m_nResult = 0;
	m_bNotifyEnd = false;
	m_setReward.clear();
	m_towerCid = 0;
	m_nStartBrushTime = 0;
	m_mapPlayerOuput.clear();
	m_mapPlayerBear.clear();
	m_pMapStar = nullptr;
	m_setRobot.clear();
	m_mapExploit.clear();
	m_setBornMonster.clear();
	m_mapAllTypeMonster.clear();
	m_mapAllMonster.clear();
	m_mapGroupMons.clear();
}

void Duplicate::OnTimer(uint32_t nTimerID)
{
	switch (nTimerID)
	{
	case ETimer_Update:
		{
			//刷怪更新
			if (nullptr != m_pBrushMonster)
			{
				m_pBrushMonster->BrushUpdate();
				m_bFinishBrush = m_pBrushMonster->FinishBrush();
			}
			//检查怪物出生
			CheckMonsBorn();
			//检测怪物行走的区域
			CheckEnterArea();
			//检测玩家hp
			CheckPlayerHp();
			//检测玩家复活倒计时
			CheckRelive();
			//更新状态
			UpdateState();

			//通知中心服副本结束
			if (m_bEnd && !m_bNotifyEnd)
			{
				//副本结束，停止刷怪
				if (nullptr != m_pBrushMonster)
				{
					m_pBrushMonster->StopBrush();
				}

				m_bNotifyEnd = true;
				//通知中心服副本结束
				g_GetDuplicateMgr()->NotifyCenterDuplicateEnd(m_nSceneID,m_nResult);
			}
		}
		break;
	case ETimer_StartBrush:
		{
			if ((int8_t)EDuplicateState::EDuplicateState_Begin == GetDuplicateState())
			{
				StartBrush();
			}
		}
		break;
	default:
		break;
	}
	//定时器更新
	OnTimerUpdate(nTimerID);
}

void Duplicate::OnExecute(uint16_t nEventID, uint64_t nSrcID, uint8_t bySrcType, void *pContext, int32_t nLen)
{
	switch (nEventID)
	{
	case EVENT_CREATURE_DEAD:
	{
		DieEvent *pDieEvent = (DieEvent*)pContext;
		CreatureDead(bySrcType, pDieEvent);
	}
	break;
	case EVENT_ENTER_SCENE:
	{
		if (nLen != sizeof(EnterSceneEvent))
		{
			LogErrFmtPrint("[logic] Duplicate::OnExecute nLen != sizeof(EnterSceneEvent)...len:%d ,sceneid:%u, mapid:%u,  duplicateid:%u ", nLen, nSrcID, m_nMapID, m_nDuplicateID);
			return;
		}
		EnterSceneEvent *pEnter = (EnterSceneEvent*)pContext;
		CreatureEnter(pEnter);
	}
	break;
	case EVENT_LEAVE_SCENE:
	{
		if (nLen != sizeof(LeaveSceneEvent))
		{
			LogErrFmtPrint("[logic] Duplicate::OnExecute nLen != sizeof(LeaveSceneEvent)...len:%d ,sceneid:%u, mapid:%u,  duplicateid:%u ", nLen, nSrcID, m_nMapID, m_nDuplicateID);
			return;
		}
		LeaveSceneEvent *pLeave = (LeaveSceneEvent*)pContext;
		CreatureLeave(pLeave, bySrcType);
	}
	break;
	case EVENT_LOGINOUT_GAME:
	{
		LogDebugFmtPrint("[logic] Duplicate::OnExecute ....EVENT_LOGINOUT_GAME ....dupid:%u, sceneid:%u ,srcid:%lu ", m_nDuplicateID, m_nSceneID, nSrcID);
		PlayerLogoutGame(nSrcID);
	}
	break;
	case EVENT_DISCONNECT:
	{
		//暂时不处理
		/*LogDebugFmtPrint("[logic] OnExecute ....EVENT_DISCONNECT ....dupid:%u, sceneid:%u ,srcid:%u ", m_nDuplicateID,m_nSceneID,nSrcID);
		Player *pPlayer = GetPlayer(nSrcID);
		if (nullptr != pPlayer)
		{
			if (IsMulDup())
			{
				UpdatePlayerOnline(pPlayer, 0);
			}
			OnDisconnect(pPlayer);
		}		*/
	}
	break;
	case EVENT_UNDER_ATTACK:
	case EVENT_ATTACK_SOMEBODY:
		{
			if (nLen != sizeof(skillAttackEvent))
			{
				LogErrFmtPrint("[logic] Duplicate::OnExecute nLen != sizeof(skillAttackEvent)...len:%d ,sceneid:%u, mapid:%u,  duplicateid:%u ", nLen, nSrcID, m_nMapID, m_nDuplicateID);
				return;
			}
			skillAttackEvent *pAttack = (skillAttackEvent*)pContext;
			CreatureAtkAndUnderAtk(pAttack);
		}
		break;
	case EVENT_LEVELUP:
		{
			if (nLen != sizeof(PlayerLeveUpEvent))
			{
				LogErrFmtPrint("[logic] Duplicate::OnExecute nLen != sizeof(PlayerLeveUpEvent)...len:%d ,sceneid:%u, mapid:%u,  duplicateid:%u ", nLen, nSrcID, m_nMapID, m_nDuplicateID);
				return;
			}
			PlayerLeveUpEvent *pLevEvent = (PlayerLeveUpEvent*)pContext;
			Player *pPlayer = GetPlayer(pLevEvent->cid);
			UpdatePlayerLev(pPlayer);
		}
		break;
	case EVENT_FACADE_CHANGE:
		{
			if (nLen != sizeof(ChangeFacadeEvent))
			{
				LogErrFmtPrint("[logic] Duplicate::OnExecute nLen != sizeof(ChangeFacadeEvent)...len:%d ,sceneid:%u, mapid:%u,  duplicateid:%u ", nLen, nSrcID, m_nMapID, m_nDuplicateID);
				return;
			}
			ChangeFacadeEvent *pFacadeEvent = (ChangeFacadeEvent*)pContext;
			Player *pPlayer = GetPlayer(pFacadeEvent->cid);
			UpdatePlayerFacade(pPlayer);
		}
		break;
	case EVENT_PLAYER_USE_MONSTER:
		{
			if (nLen != sizeof(UseMonsEvent))
			{
				LogErrFmtPrint("[logic] Duplicate::OnExecute nLen != sizeof(UseMonsEvent)...len:%d ,sceneid:%u, mapid:%u,  duplicateid:%u ", nLen, nSrcID, m_nMapID, m_nDuplicateID);
				return;
			}
			UseMonsEvent *pUseThing = (UseMonsEvent*)pContext;
			//目前这个事件只有阻挡那边用到
			m_dupBlock.OnUseThing(pUseThing->monsId);
		}
		break;
	default:
		break;
	}
	//执行事件
	OnExecuteEvent(nEventID, nSrcID, bySrcType, pContext, nLen);
}

//获取副本ID
uint32_t Duplicate::GetDuplicateID()
{
	return m_nDuplicateID;
}
//获取场景ID
uint32_t Duplicate::GetSceneID()
{
	return m_nSceneID;
}
//获取地图ID
uint32_t Duplicate::GetMapID()
{
	return m_nMapID;
}
//获取开始时间
uint64_t Duplicate::GetStartTime()
{
	return m_nStartTime;
}
//获取副本类型
int8_t Duplicate::GetType()
{
	return m_byType;
}
//获取副本额外参数
DExParam &Duplicate::GetExParam()
{
	return m_paramEx;
}
//获取副本配置信息
const DuplicateDuplicateCfgInfo *Duplicate::GetDuplicateCfgInfo()
{
	return m_pDuplicateCfg;
}

//获取场景玩家
Player *Duplicate::GetPlayer(CharIDType pcid)
{
	SET_UINT64::iterator iter = m_setPlayer.find(pcid);
	if (iter != m_setPlayer.end())
	{
		return  g_GetCreatureMgr()->GetNoScenePlayer((*iter));
	}
	return nullptr;
}
//删除玩家
void Duplicate::DelPlayer(CharIDType cid)
{
	m_setPlayer.erase(cid);
}
//获取场景玩家数量
uint32_t Duplicate::GetPlayerCount()
{
	return (uint32_t)m_setPlayer.size();
}
//获取场景怪物
Monster *Duplicate::GetMonster(CharIDType mcid)
{
	SET_UINT64::iterator iter = m_setMonster.find(mcid);
	if (iter != m_setMonster.end())
	{
		return m_pScene->GetMonster((*iter));
	}
	return  nullptr;
}
//获取场景NPC
Npc *Duplicate::GetNpc(CharIDType ncid)
{
	SET_UINT64::iterator iter = m_setNpc.find(ncid);
	if (iter != m_setNpc.end())
	{
		return m_pScene->GetNpc((*iter));
	}
	return  nullptr;
}

//获取机器人
CRebot *Duplicate::GetRobot(CharIDType rcid)
{
	SET_UINT64::iterator iter = m_setRobot.find(rcid);
	if (iter != m_setRobot.end())
	{
		return m_pScene->GetRebot((*iter));
	}
	return  nullptr;

}
//生物进入副本
void Duplicate::CreatureEnter(EnterSceneEvent *pEnterEvent)
{
	Creature *pCreature = m_pScene->GetCreature(pEnterEvent->cId);
	if (nullptr != pCreature)
	{
		if (CREATURE_MONSTER == pCreature->CreatureKind())
		{
			m_setMonster.insert(pEnterEvent->cId);
			//
			SET_UINT64 setBorn;
			setBorn.clear();
			setBorn.insert(pEnterEvent->cId);
			AddBornMonster(setBorn);
			//
			Monster *pMonster = dynamic_cast<Monster*>(pCreature);
			if (nullptr != pMonster)
			{
				//记录怪物组
				AddMonsByGroup(pMonster->GetCid(), pMonster->GetFormationId());
			}			
		}
		else if (CREATURE_REBOT == pCreature->CreatureKind())
		{
			m_setRobot.insert(pCreature->GetCid());
		}
		else if (CREATURE_NPC == pCreature->CreatureKind())
		{
			m_setNpc.insert(pCreature->GetCid());
		}
		else if (CREATURE_PLAYER == pCreature->CreatureKind())
		{
			//第一个玩家进入场景就会开始刷怪
			if (0 == m_nStartBrushTime)
			{
				m_nStartBrushTime = g_GetGlobalServerTime()->UnixSec();
			}
			//通知玩家进入副本成功
			CharIDType cid = pCreature->GetCid();
			Player *pPlayer = dynamic_cast<Player*>(pCreature);
			if (IsMulDup())
			{
				//初始化玩家输出伤害
				MAP_UINT64_UINT64::iterator iterOutput = m_mapPlayerOuput.find(cid);
				if (iterOutput == m_mapPlayerOuput.end())
				{
					m_mapPlayerOuput[cid] = 0;
				}
				//初始化承受伤害值
				MAP_UINT64_UINT64::iterator iterBear = m_mapPlayerBear.find(cid);
				if (iterBear == m_mapPlayerBear.end())
				{
					m_mapPlayerBear[cid] = 0;
				}
				//初始化生命
				m_mapPlayerLastHp[cid] = pPlayer->GetAttr(C_HP);
			}
			
			//添加到玩家列表
			m_setPlayer.insert(cid);

			if ((int8_t)EDuplicateState::EDuplicateState_Ready == GetDuplicateState())
			{
				//如果是准备状态，则转到副本开始状态
				SetDuplicateState((int8_t)EDuplicateState::EDuplicateState_Begin);
			}
			//进入副本成功
			OnEnterSuccess(cid);
			//返回客户端
			Part *pPart = pPlayer->GetPart(PART_DUPLICATE);
			if (nullptr != pPart)
			{
				DupEnterParam enterParam;
				GetEnterParam(enterParam);
				//通知进入副本成功
				pPart->NotifyEnterSuccess(enterParam);
			}
			//进入副本协议一定要在副本开始协议之后
			g_GetDuplicateMgr()->NotifyCenterEnterDuplicate(m_nSceneID, pEnterEvent->cId,RET_SUCCESS);
			//角色进副本 订阅事件
			OnPlayerEnterEvent(cid);
			//曾经进入过副本,这个需要放到 NotifyEnterSuccess 之后
			m_setOnceEnter.insert(cid);	

			//进入副本事件
			EnterDupEvent enterEvent;
			enterEvent.dupId = m_nDuplicateID;
			g_GetEvent()->FireExecute(EVENT_ENTER_DUPLICATE, cid, CREATURE_PLAYER, &enterEvent, sizeof(EnterDupEvent));
		}
	}
	OnCreatureEnter(pCreature);
}
//生物离开
void Duplicate::CreatureLeave(LeaveSceneEvent *pLeaveEvent, uint8_t bySrcType)
{
	if (CREATURE_MONSTER == bySrcType)
	{
	}
	else if (CREATURE_PLAYER == bySrcType)
	{
		LogDebugFmtPrint("[logic] Duplicate::CreatureLeave....dupid:%u, sceneid:%u ,cid:%lu ", m_nDuplicateID, m_nSceneID, pLeaveEvent->cId);
		PlayerLeave(pLeaveEvent->cId);
	}
}

//生物攻击受击
void Duplicate::CreatureAtkAndUnderAtk(skillAttackEvent *pEventAtk)
{
	if (nullptr == pEventAtk)
	{
		return;
	}
	if (m_towerCid > 0 && m_towerCid == pEventAtk->victim)
	{
		Monster *pMonster = GetMonster(m_towerCid);
		if (nullptr != pMonster)
		{
			m_pCond->onMonsHpUpdate(pMonster->GetAttr(C_HP));
		}
	}
	//多人的时候才会更新战斗数值
	if (IsMulDup())
	{
		UpdatePlayerHarm(pEventAtk->attacker, pEventAtk->victim, pEventAtk->sufferedValue);
	}
}


//通过怪物组增加怪物
void Duplicate::AddMonsByGroup(CharIDType monsCid, int32_t groupId)
{
	MAP_UINT32_SET_UINT64::iterator iter = m_mapGroupMons.find(groupId);
	if (iter != m_mapGroupMons.end())
	{
		iter->second.insert(monsCid);
	}
	else
	{
		SET_UINT64 setMons;
		setMons.clear();
		setMons.insert(monsCid);
		m_mapGroupMons[groupId] = setMons;
	}
}
//通过副本组移除怪物
void Duplicate::DelMonsByGroup(CharIDType monsCid, int32_t groupId)
{
	MAP_UINT32_SET_UINT64::iterator iter = m_mapGroupMons.find(groupId);
	if (iter != m_mapGroupMons.end())
	{
		SET_UINT64 &setMons = iter->second;
		SET_UINT64::iterator iterMons = setMons.find(monsCid);
		if (iterMons != setMons.end())
		{
			setMons.erase(iterMons);
		}
		if (setMons.size() == 0)
		{
			m_mapGroupMons.erase(iter);
		}
	}
}

//下线
void Duplicate::PlayerLogoutGame(CharIDType charId)
{
	Player *pPlayer = GetPlayer(charId);
	if (nullptr == pPlayer)
	{
		LogErrFmtPrint("[logic] Duplicate::PlayerLogoutGame... nullptr == pPlayer ... charid:%lu ",charId);
		return;
	}
	//
	if (IsMulDup())
	{
		UpdatePlayerOnline(pPlayer, 0);
	}
	//
	PlayerLeave(charId);
}

//主动离开副本之前 的处理
void Duplicate::OnActiveBeforeLeave(CharIDType cid)
{
	//离开副本的时候如果是死亡状态的话,离开之后需要复活下
	Player *pPlayer = GetPlayer(cid);
	if (nullptr != pPlayer && pPlayer->IsDead())
	{
		LogDebugFmtPrint("[logic] Duplicate::OnActiveBeforeLeave...dupid:%u, sceneid:%u, mapid:%u, cid:%lu, hp:%ld ", m_nDuplicateID,m_nSceneID,m_nMapID,cid,pPlayer->GetAttr(C_HP));
		pPlayer->OnRevive(pPlayer->GetCid());
	}
	if (nullptr != m_pCond)//目前只有竞技场用到、阵营首领挑战、切磋
	{
		m_pCond->onPlayerLeave(cid);
	}
}

//生物离开副本
void Duplicate::PlayerLeave(CharIDType cid)
{
	LogDebugFmtPrint("[logic] Duplicate::PlayerLeave 11....cid:%lu, dupid:%u, sceneid:%u ", cid,m_nDuplicateID,m_nSceneID);
	if (!OnCommon_PlayerLeave(cid))
	{
		return;
	}
	//处理离开副本
	bool bEnd = false;
	bool bDestory = false;
	if (0 == GetPlayerCount())
	{
		bDestory = true; //需要销毁
		if (!m_bEnd) //如果还没结束，需要设置为结束
		{
			bEnd = true;
		}
	}

	if (bEnd)
	{
		m_bEnd = true;
		m_nResult = RET_FAIL;
	}

	LogDebugFmtPrint("[logic] Duplicate::PlayerLeave...duplicateid:%u ,sceneid:%u ,mapid:%u， cid:%lu  ", m_nDuplicateID, m_nSceneID, m_nMapID, cid);

	if (bDestory)
	{
		SetDuplicateState((int8_t)EDuplicateState::EDuplicateState_Destory);
	}
}

//复活超时
void Duplicate::ReliveTimeOut(CharIDType cid)
{
	Player *pPlayer = GetPlayer(cid);
	if (nullptr == pPlayer)
	{
		LogErrFmtPrint("[logic] Duplicate::ReliveTimeOut .... nullptr == pPlayer  dupid:%u, sceneid:%u, cid:%lu ",m_nDuplicateID,m_nSceneID,cid);
		return;
	}
	if (!pPlayer->IsDead())
	{
		return;
	}
	LogErrFmtPrint("[logic] Duplicate::ReliveTimeOut .... dupid:%u, sceneid:%u, cid:%lu ", m_nDuplicateID, m_nSceneID, cid);
	if (!Relive(pPlayer))
	{
		LogErrFmtPrint("[logic] Duplicate::ReliveTimeOut relive failed....dupid:%u, sceneid:%u, cid:%lu ", m_nDuplicateID, m_nSceneID, cid);
	}
}

//生物死亡
void Duplicate::CreatureDead(int8_t byKind,DieEvent *pDieEvent)
{
	if (nullptr == pDieEvent)
		return;

	//生物死亡，通知条件
	if (nullptr != m_pCond)
	{
		bool flag = true;
		if (CREATURE_REBOT == byKind) //竞技场订阅的是机器人死亡事件，需要判断下是否是当前副本中的机器人
		{
			if (!GetRobot(pDieEvent->nCid))
			{
				flag = false;
			}
		}
		if (flag)
		{
			m_pCond->onCreatrueDie(pDieEvent->nCid, byKind);
		}
	}

	//LogDebugFmtPrint("[logic]  Duplicate::CreatureDead....cid:%llu, kind:%d, dupid:%u, sceneid:%u ", pDieEvent->nCid, byKind, m_nDuplicateID, m_nSceneID);
	if (CREATURE_MONSTER == byKind)
	{
		Monster *pMonster = GetMonster(pDieEvent->nCid);
		if (nullptr == pMonster)
		{
			return;
		}
		int8_t parentType = pMonster->GetParentMonsterType();
		int32_t formationId = pMonster->GetFormationId();
		LogDebugFmtPrint("[logic]  Duplicate::CreatureDead....monster cid:%lu, monsterid:%u ,num:%u, formationId:%d,parentType:%d, dupid:%u, sceneid:%u ", pDieEvent->nCid, pDieEvent->monsterId, pDieEvent->count, formationId, parentType,m_nDuplicateID, m_nSceneID);
		if (GetPlayer(pDieEvent->killerCid))
		{
			MAP_UINT64_UINT32::iterator iter = m_mapKillNum.find(pDieEvent->killerCid);
			if (iter != m_mapKillNum.end())
			{
				iter->second += pDieEvent->count;
			}
			else
			{
				m_mapKillNum[pDieEvent->killerCid] = 1;
			}
		}
		//剩余怪物处理
		MAP_INT8_MAP_UINT32_UINT32::iterator iterType = m_mapAllTypeMonster.find(parentType);
		if (iterType != m_mapAllTypeMonster.end())
		{
			MAP_UINT32_UINT32 &mapMonster = iterType->second;
			MAP_UINT32_UINT32::iterator iterMon = mapMonster.find(pDieEvent->monsterId);
			if (iterMon != mapMonster.end())
			{
				if (iterMon->second >= (uint32_t)pDieEvent->count)
				{
					iterMon->second -= pDieEvent->count;
				}
				else
				{
					iterMon->second = 0;
				}
				//总剩余怪物处理
				if (m_monsterNum >= pDieEvent->count)
				{
					m_monsterNum -= pDieEvent->count;
				}
				else
				{
					m_monsterNum = 0;
				}
			}
		}
		//怪物死亡，通知刷怪
		if (nullptr != m_pBrushMonster)
		{
			m_pBrushMonster->OnMonterDead(pDieEvent->nCid,pDieEvent->monsterId, pDieEvent->count, pMonster->GetFormationId(),pDieEvent->killerCid);
		}
		//怪物死亡，阻挡通知
		m_dupBlock.OnMonsDie(pDieEvent->monsterId, pDieEvent->count, pMonster->GetFormationId());
		//怪物死亡，通知条件
		if (nullptr != m_pCond)
		{
			m_pCond->onMonDie(pDieEvent->monsterId, pDieEvent->count, m_monsterNum);
		}
		//怪物死亡，星级通知
		//m_dupStar.monsDead(pDieEvent->monsterId, pDieEvent->count, (int32_t)pMonster->GetParentMonsterType());

		//删除怪物组怪物
		DelMonsByGroup(pMonster->GetCid(), pMonster->GetFormationId());

		//记录所有怪物死亡数量
		auto iterDie = m_mapAllDieMonter.find(pDieEvent->monsterId);
		if (iterDie != m_mapAllDieMonter.end())
		{
			iterDie->second += 1;
		}
		else
		{
			m_mapAllDieMonter[pDieEvent->monsterId] = pDieEvent->count;
		}
		//取消订阅受攻击事件
		g_GetEvent()->UnSubscribe(this, EVENT_UNDER_ATTACK, pDieEvent->nCid, 0);
		//删除怪物
		m_setMonster.erase(pDieEvent->nCid);
	}
	else if (CREATURE_PLAYER == byKind)
	{
		Player *pPlayer = GetPlayer(pDieEvent->nCid);
		if (nullptr != pPlayer)
		{
			if (!IsUnionHomeDup() && !IsUnionDungeonDup()) //非工会驻地，非工会地宫
			{
				//通知玩家死亡，这里只要是在副本中死亡，都发给前端，具体的需不需要显示复活对话框，前端自己处理
				Duplicate_NotifyDieRsp rsp;
				pPlayer->SendDataToClient(EMODULE_ID_DUPLICATE, LOGIC_TO_CLIENT_DUPLICATE_NOTIFY_DEAD, &rsp);
			}
			if (IsNeedRelive()) //需要复活的才需要记录死亡时间，复活超时用的
			{
				//记录玩家死亡时间
				AddPlayerDieSec(pDieEvent->nCid, g_GetGlobalServerTime()->UnixSec());
			}

			//增加死亡次数
			AddPlayerDieNum(pDieEvent->nCid);
			//人物死亡，星级更新
			//m_dupStar.playerDead();
			//多人副本 广播玩家状态
			if (IsMulDup())
			{
				UpdatePlayerDie(pPlayer, 1);
			}
		}
	}
	else if (CREATURE_NPC == byKind)
	{
		Npc *pNpc = GetNpc(pDieEvent->nCid);
		if (nullptr != pNpc)
		{
			m_setNpc.erase(pDieEvent->nCid);
		}
	}
}

//玩家死亡数量
uint32_t Duplicate::GetPlayerDieNum(CharIDType cid)
{
	MAP_UINT64_UINT32::iterator iter = m_mapDieNum.find(cid);
	return (iter != m_mapDieNum.end()) ? iter->second : 0;
}
//增加玩家死亡次数
void Duplicate::AddPlayerDieNum(CharIDType cid)
{
	//增加死亡次数
	MAP_UINT64_UINT32::iterator iter = m_mapDieNum.find(cid);
	if (iter != m_mapDieNum.end())
	{
		iter->second += 1;
	}
	else
	{
		m_mapDieNum[cid] = 1;
	}
}
//玩家击杀怪物数量
uint32_t Duplicate::GetPlayerKillNum(CharIDType cid)
{
	MAP_UINT64_UINT32::iterator iter = m_mapKillNum.find(cid);
	return (iter != m_mapKillNum.end()) ? iter->second : 0;
}
//获取死亡怪物数量
uint32_t Duplicate::GetDieMonsterNum(uint32_t monsterId)
{
	MAP_UINT32_UINT32::iterator iter = m_mapAllDieMonter.find(monsterId);
	return (iter != m_mapAllDieMonter.end()) ? iter->second : 0;
}	
//获取额外的死亡怪怪物数量
uint32_t Duplicate::GetDieMonsterNumExcept(SET_UINT32 &setExcept)
{
	uint32_t exceptNum = 0;
	MAP_UINT32_UINT32::iterator iterDie = m_mapAllDieMonter.begin();
	for (; iterDie != m_mapAllDieMonter.end(); ++iterDie)
	{
		SET_UINT32::iterator iterB = setExcept.find(iterDie->first);
		if (iterB == setExcept.end())
		{
			exceptNum += iterDie->second;
		}
	}
	return exceptNum;
}
//获取角色死亡时间
uint64_t Duplicate::GetPlayerDieSec(CharIDType cid)
{
	MAP_UINT64_UINT64::iterator iter = m_mapPlayerRelive.find(cid);
	return (iter != m_mapPlayerRelive.end()) ? iter->second : 0;
}
//添加角色死亡时间
void Duplicate::AddPlayerDieSec(CharIDType cid, uint64_t sec)
{
	m_mapPlayerRelive[cid] = sec;
}
//删除角色死亡时间
void Duplicate::DelPlayerDieSec(CharIDType cid)
{
	m_mapPlayerRelive.erase(cid);
}
//增加玩家复活次数
void Duplicate::AddPlayerReliveNum(CharIDType cid)
{
	//记录玩家复活相关数据
	MAP_UINT64_UINT32::iterator iterRelive = m_mapReliveNum.find(cid);
	if (iterRelive != m_mapReliveNum.end())
	{
		iterRelive->second += 1;
	}
	else
	{
		m_mapReliveNum[cid] = 1;
	}
}
//塔的配置ID（怪物ID）
uint32_t Duplicate::TowerId()
{
	if (nullptr != m_pCond)
	{
		return m_pCond->towerMonsId();
	}
	return 0;
}
//获取怪物剩余数量
int32_t Duplicate::GetMonsterNum()
{
	return m_monsterNum;
}

//获取指定怪物类型序列剩余数量
int32_t Duplicate::GetMonsterNum(SET_INT32 &setType)
{
	int32_t monsNum = 0;
	if (setType.size() <= 0)
	{
		monsNum = GetMonsterNum();
	}
	else
	{
		SET_INT32::iterator iterType = setType.begin();
		for (; iterType != setType.end(); ++iterType)
		{
			monsNum += GetMonsNumByType((int8_t)(*iterType));
		}
		
	}
	return monsNum;
}

//获取指定怪物ID的剩余数量
int32_t Duplicate::GetMonsterLeftNum(uint32_t monsterId)
{
	const MonsterMonsterCfgInfo *pMonsCfg = g_GetMonsterMonsterCfgTable()->GetMonsterMonsterCfgInfo(monsterId);
	if (nullptr == pMonsCfg)
	{
		return 0;
	}
	return GetMonsNumByType(pMonsCfg->parentType, monsterId);
}

//获取指定怪物ID的总数量
int32_t Duplicate::GetMonsterTotalNum(uint32_t monsterId)
{
	MAP_UINT32_INT32::iterator iter = m_mapAllMonster.find(monsterId);
	if (iter != m_mapAllMonster.end())
	{
		return iter->second;
	}
	return 0;
}

//是否脚本刷出的怪物全部死亡
bool Duplicate::IsBrushMonsAllDie()
{
	if (nullptr != m_pBrushMonster)
	{
		return m_pBrushMonster->BrushMonsAllDie();
	}
	return false;
}

//离开队伍
void Duplicate::LeaveTeam(CharIDType charId)
{
	if (IsTeamDup())
	{
		Player *pPlayer = GetPlayer(charId);
		if (nullptr != pPlayer)
		{
			LogDebugFmtPrint("[logic] Duplicate::LeaveTeam....cid:%lu, dupid:%u, sceneid:%u ", charId,m_nDuplicateID,m_nSceneID);
			LeaveDuplicate(pPlayer);
		}
	}
}
//离开房间
void Duplicate::LeaveRoom(CharIDType charId)
{
	if (IsRoomDup())
	{
		Player *pPlayer = GetPlayer(charId);
		if (nullptr != pPlayer)
		{
			LogDebugFmtPrint("[logic] Duplicate::LeaveRoom....cid:%lu, dupid:%u, sceneid:%u ", charId, m_nDuplicateID, m_nSceneID);
			LeaveDuplicate(pPlayer);
		}
	}
}

//重连数据
void Duplicate::OnReconnect(CharIDType cid)
{
	Player *pPlayer = GetPlayer(cid);
	if (nullptr == pPlayer)
	{
		LogErrFmtPrint("[logic] Duplicate::OnReconnect...nullptr == pPlayer ...cid:%lu, dup:%u, sceneid:%u, mapid:%u ,keytype:%u, keyvalue:%lu ",cid,m_nDuplicateID,m_nSceneID,m_nMapID,m_paramEx.byKeyType,m_paramEx.keyValue);
		return;
	}
	DuplicatePart *pDupPart = dynamic_cast<DuplicatePart*>(pPlayer->GetPart(PART_DUPLICATE));
	if (nullptr == pDupPart)
	{
		LogErrFmtPrint("[logic] Duplicate::OnReconnect....nullptr == pDupPart...cid:%lu, dup:%u, sceneid:%u, mapid:%u ,keytype:%u, keyvalue:%lu ", cid, m_nDuplicateID, m_nSceneID, m_nMapID, m_paramEx.byKeyType, m_paramEx.keyValue);
		return;
	}
	DupEnterParam enterParam;
	GetEnterParam(enterParam);
	pDupPart->NotifyReconnect(enterParam);
}

//获取指定怪物组的怪物
void Duplicate::GetMonsByGroup(SET_INT32 &setGroup, MAP_UINT32_SET_UINT64 &mapGroupMons)
{
	SET_INT32::const_iterator iterGroup = setGroup.begin();
	for (; iterGroup != setGroup.end(); ++iterGroup)
	{
		int32_t groupId = (*iterGroup);
		MAP_UINT32_SET_UINT64::iterator iter = m_mapGroupMons.find(groupId);
		if (iter != m_mapGroupMons.end())
		{
			SET_UINT64 &setMons = iter->second;
			mapGroupMons[groupId] = setMons; //这里的怪物组ID不会重复，所以可以直接覆盖
		}
	}
}
//开始刷怪
uint64_t Duplicate::StartBrushTime()
{
	return m_nStartBrushTime;
}

//获取副本剩余时间
int32_t Duplicate::LeftSec()
{
	int32_t ilimitSec = m_pCond->limitSec();
	int32_t leftSec = ilimitSec;
	uint64_t curTime = g_GetGlobalServerTime()->UnixSec();
	if (curTime >= m_nStartBrushTime)
	{
		leftSec = (int32_t)(ilimitSec - (curTime - m_nStartBrushTime));
		leftSec = (leftSec < 0) ? 0 : leftSec;
	}
	return leftSec;
}

//获取塔的血量
void Duplicate::GetTowerInfo(uint64_t &curHp,uint64_t &maxHp)
{
	if (m_towerCid > 0)
	{
		Monster *pmonster = GetMonster(m_towerCid);
		if (nullptr != pmonster)
		{
			curHp = pmonster->GetAttr(C_HP);
			maxHp = pmonster->GetAttr(C_MAX_HP);
		}
	}
}

//获取以传送的怪物数量
int32_t Duplicate::GetTransNum()
{
	int32_t transNum = 0;
	if (nullptr != m_pCond)
	{
		transNum = m_pCond->getTransNum();
	}
	return transNum;
}
//获取玩家进入之前的区域
uint32_t Duplicate::GetBeforeArea(CharIDType charId)
{
	MAP_UINT64_UINT32::iterator iter = m_paramEx.mapArea.find(charId);
	return (iter != m_paramEx.mapArea.end()) ? iter->second : 0;
}
//副本场景广播
void Duplicate::BroadCastData(uint16_t moduleId, uint16_t cmdId, ProtoBufBase *pbuf)
{
	SET_UINT64::iterator iter = m_setPlayer.begin();
	for (; iter != m_setPlayer.end(); ++iter)
	{
		Player *pPlayer = GetPlayer((*iter));
		if (nullptr != pPlayer)
		{
			pPlayer->SendDataToClientEx(moduleId, cmdId, pbuf);
		}
	}
}
//获取星级状态
int8_t Duplicate::GetStartState(MAP_INT8_INT8 &mapState)
{
	return m_dupStar.getStarState(mapState);
}

//获取阻挡状态
void Duplicate::GetBlockState(MAP_UINT32_INT8 &mapBlockState)
{
	m_dupBlock.GetAllBlockState(mapBlockState);
}

//开始刷怪
void Duplicate::StartBrush()
{
	if (nullptr != m_pBrushMonster)
	{
		m_pBrushMonster->StartBrush();
	}	
}

//检查死亡复活
void Duplicate::CheckRelive()
{
	uint64_t curTime = g_GetGlobalServerTime()->UnixSec();
	MAP_UINT64_UINT64 mapPlayerRelive = m_mapPlayerRelive;
	MAP_UINT64_UINT64::iterator iter = mapPlayerRelive.begin();
	while (iter != mapPlayerRelive.end())
	{
		if (GetPlayerDieSec(iter->first) > 0)
		{
			if (curTime - iter->second >= (uint64_t)m_reliveSec)
			{
				//复活超时
				ReliveTimeOut(iter->first);
				//
				iter = mapPlayerRelive.erase(iter);
				continue;
			}
		}	

		++iter;
	}
}

//检查副本准备状态
void Duplicate::CheckReadyState()
{
	if (GetDuplicateState() == (int8_t)EDuplicateState::EDuplicateState_Ready)
	{
		uint64_t curTime = g_GetGlobalServerTime()->UnixSec();
		if (curTime - m_nReadyStartTime >= EMaxReadyStateSec)
		{
			//准备状态超时
			m_bReadyTimeOut = true;
			if (!m_bEnd)
			{
				m_bEnd = true;
				m_nResult = RET_FAIL;
				SetDuplicateState((int8_t)EDuplicateState::EDuplicateState_Clean);
			}
		}
	}
}

//更新状态
void Duplicate::UpdateState()
{
	int8_t byState = GetDuplicateState();
	switch (byState)
	{
	case (int8_t)EDuplicateState::EDuplicateState_Ready:
	{
		CheckReadyState();
		/*if (m_mapPlayer.size() >= 1)
		{
			SetDuplicateState((int8_t)EDuplicateState::EDuplicateState_Begin);
		}
		else
		{
			CheckReadyState();
		}*/
	}
	break;
	case (int8_t)EDuplicateState::EDuplicateState_Begin:
	{
		//这里检查副本完成条件（成功，失败）,如果副本完成，设置副本完成状态
		int32_t ret = CheckEnd();
		if (RET_SUCCESS == ret || RET_FAIL == ret || RET_COMPETE_DRAW == ret/*切磋平局*/)
		{
			//结束
			m_bEnd = true;
			m_nResult = ret;
			SetDuplicateState((int8_t)EDuplicateState::EDuplicateState_Finish);
		}
	}
	break;
	case (int8_t)EDuplicateState::EDuplicateState_Finish:
	{
	}
	break;
	case (int8_t)EDuplicateState::EDuplicateState_Flop:
	{

	}
	break;
	case (int8_t)EDuplicateState::EDuplicateState_Clean:
	{

	}
	break;
	case (int8_t)EDuplicateState::EDuplicateState_Destory:
	{

	}
	break;
	default:
		break;
	}
}
//获取玩家输出伤害
uint64_t Duplicate::GetPlayerOutput(CharIDType cid)
{
	MAP_UINT64_UINT64::iterator iter = m_mapPlayerOuput.find(cid);
	return (iter != m_mapPlayerOuput.end()) ? iter->second : 0;
}
//获取玩家承受伤害
uint64_t Duplicate::GetPlayerBear(CharIDType cid)
{
	MAP_UINT64_UINT64::iterator iter = m_mapPlayerBear.find(cid);
	return (iter != m_mapPlayerBear.end()) ? iter->second : 0;
}
//更新玩家伤害
void Duplicate::UpdatePlayerHarm(CharIDType atkSide, CharIDType bearSide, int32_t harmValue)
{
	//LogDebugFmtPrint("[logic] Duplicate::UpdatePlayerHarm...atkside:%lu, bearside:%lu, harmValue:%d ",atkSide,bearSide,harmValue);
	SET_UINT64 setPlayer;
	setPlayer.clear();
	if (GetPlayer(atkSide))
	{
		MAP_UINT64_UINT64::iterator iter = m_mapPlayerOuput.find(atkSide);
		if (iter != m_mapPlayerOuput.end())
		{
			iter->second += harmValue;
		}
		else
		{
			m_mapPlayerOuput[atkSide] = (uint64_t)harmValue;
		}
		setPlayer.insert(atkSide);
	}
	if (GetPlayer(bearSide))
	{
		MAP_UINT64_UINT64::iterator iter = m_mapPlayerBear.find(bearSide);
		if (iter != m_mapPlayerBear.end())
		{
			iter->second += harmValue;
		}
		else
		{
			m_mapPlayerOuput[bearSide] = (uint64_t)harmValue;
		}
		setPlayer.insert(bearSide);
	}
	if (setPlayer.size() > 0)
	{
		Duplicate_FightDataRsp fighRsp;
		auto iterCid = setPlayer.begin();
		for (; iterCid != setPlayer.end(); ++iterCid)
		{
			CharIDType cid = (*iterCid);
			DupFightDataProto *proto = fighRsp.add_fight_data();
			if (nullptr != proto)
			{
				proto->set_cid(cid);
				proto->set_atk(GetPlayerOutput(cid));
				proto->set_be_atk(GetPlayerBear(cid));
			}
		}
		//广播战斗数据
		BroadCastData(EMODULE_ID_DUPLICATE, LOGIC_TO_CLIENT_DUPLICATE_FIGHT_DATA, &fighRsp);
	}
}

//更新玩家生命
void Duplicate::UpdatePlayerHp(Player *pPlayer)
{
	if (nullptr == pPlayer)
	{
		return;
	}
	Duplicate_NotifyCharHpRsp rsp;
	DupAllCharHpProto *proto = rsp.mutable_char_hp();
	if (nullptr != proto)
	{
		DupCharHpProto *protoHp = proto->add_all_hp();
		if (nullptr != protoHp)
		{
			protoHp->set_cid(pPlayer->GetCid());
			protoHp->set_hp(pPlayer->GetAttr(C_HP));
			protoHp->set_max_hp(pPlayer->GetAttr(C_MAX_HP));
		}
	}
	BroadCastData(EMODULE_ID_DUPLICATE, LOGIC_TO_CLIENT_DUPLICATE_NOTIFY_HP, &rsp);
}
//更新玩家等级
void Duplicate::UpdatePlayerLev(Player *pPlayer)
{
	if (nullptr == pPlayer)
	{
		return;
	}
	Duplicate_NotifyCharLevRsp rsp;
	DupAllCharLevProto *proto = rsp.mutable_char_lev();
	if (nullptr != proto)
	{
		DupCharLevProto *protoLev = proto->add_all_lev();
		if (nullptr != protoLev)
		{
			protoLev->set_cid(pPlayer->GetCid());
			protoLev->set_level(pPlayer->GetAttr(C_LEVEL));
		}
	}
	BroadCastData(EMODULE_ID_DUPLICATE, LOGIC_TO_CLIENT_DUPLICATE_NOTIFY_LEVEL, &rsp);
}
//更新玩家信息
void Duplicate::UpdatePlayerInfo(Player *pPlayer)
{
	if (nullptr == pPlayer)
	{
		return;
	}
	Duplicate_NotifyCharRsp rsp;
	DupAllCharProto *proto = rsp.mutable_char_info();
	if (nullptr != proto)
	{
		DupCharProto *protoChar = proto->add_all_char();
		if (nullptr != protoChar)
		{
			protoChar->set_cid(pPlayer->GetCid());
			protoChar->set_name(pPlayer->GetName());
			protoChar->set_prof(pPlayer->GetAttr(C_PROF));
			protoChar->set_sex(pPlayer->GetAttr(C_GENDER));
			int32_t leaderFlag = 0;
			if (EDuplicateKeyType_Room == m_paramEx.byKeyType && pPlayer->GetAttr(C_ROOM_LEADER_ID))
			{
				leaderFlag = 1;
			}
			else if (EDuplicateKeyType_Team == m_paramEx.byKeyType && pPlayer->GetAttr(C_TEAM_LEADER_ID))
			{
				leaderFlag = 1;
			}
			protoChar->set_leader_falg(leaderFlag);
		}
	}
	BroadCastData(EMODULE_ID_DUPLICATE, LOGIC_TO_CLIENT_DUPLICATE_NOTIFY_CHAR_INFO, &rsp);
}
//更新玩家外观
void Duplicate::UpdatePlayerFacade(Player *pPlayer)
{
	if (nullptr == pPlayer)
	{
		return;
	}
	Duplicate_NotifyCharFacadeRsp rsp;
	DupAllCharFacadeProto *proto = rsp.mutable_char_facade();
	if (nullptr != proto)
	{
		DupCharFacadeProto *protoFacade = proto->add_all_facade();
		if (nullptr != protoFacade)
		{
			protoFacade->set_cid(pPlayer->GetCid());
			CharFacadeProto *protoCharFacade = protoFacade->mutable_facade();
			if (nullptr != protoCharFacade)
			{
				pPlayer->GetFacade(protoCharFacade);
			}			
		}
	}
	BroadCastData(EMODULE_ID_DUPLICATE, LOGIC_TO_CLIENT_DUPLICATE_NOTIFY_FACADE, &rsp);
}

//更新玩家在线状态
void Duplicate::UpdatePlayerOnline(Player *pPlayer, int32_t onlineState)
{
	if (nullptr == pPlayer)
	{
		return;
	}
	Duplicate_NotifyCharOnlineRsp rsp;
	DupAllCharOnlineProto *protoAllChar = rsp.mutable_char_online();
	if (nullptr != protoAllChar)
	{
		DupCharOnlineProto *protoChar = protoAllChar->add_all_online();
		if (nullptr != protoChar)
		{
			protoChar->set_cid(pPlayer->GetCid());
			protoChar->set_online_flag(onlineState);
		}
	}
	BroadCastData(EMODULE_ID_DUPLICATE, LOGIC_TO_CLIENT_DUPLICATE_NOTIFY_ONLINE, &rsp);
}

//更新玩家死亡状态
void Duplicate::UpdatePlayerDie(Player *pPlayer, int32_t dieState)
{
	if (nullptr == pPlayer)
	{
		return;
	}
	Duplicate_NotifyCharDieRsp rsp;
	DupAllCharDieProto *protoAllChar = rsp.mutable_char_die();
	if (nullptr != protoAllChar)
	{
		DupCharDieProto *protoChar = protoAllChar->add_all_die();
		if (nullptr != protoChar)
		{
			protoChar->set_cid(pPlayer->GetCid());
			protoChar->set_die_flag(dieState);
		}
	}
	BroadCastData(EMODULE_ID_DUPLICATE, LOGIC_TO_CLIENT_DUPLICATE_NOTIFY_DIE, &rsp);
}

//更新副本功勋
void Duplicate::UpdatePlayerExploit(Player *pPlayer, int32_t exploit)
{
	if (nullptr == pPlayer)
	{
		return;
	}
	Duplicate_UpdateExploitRsp rsp;
	rsp.set_exploit(exploit);
	pPlayer->SendDataToClient(EMODULE_ID_DUPLICATE, LOGIC_TO_CLIENT_DUPLICATE_UPDATE_EXPLOIT, &rsp);
}


//获取玩家上一次的生命值
uint32_t Duplicate::GetPlayerLastHp(CharIDType cid)
{
	MAP_UINT64_UINT32::iterator iter = m_mapPlayerLastHp.find(cid);
	return (iter != m_mapPlayerLastHp.end()) ? iter->second : 0;
}
//设置玩家上一次的生命值
void Duplicate::SetPlayerLastHp(CharIDType cid, uint32_t hp)
{
	m_mapPlayerLastHp[cid] = hp;
}

//检查玩家生命值
void Duplicate::CheckPlayerHp()
{
	if (!IsRoomDup()) //组队副本血量走组队副本那边
	{
		return;
	}
	SET_UINT64::iterator iter = m_setPlayer.begin();
	for (; iter != m_setPlayer.end(); ++iter)
	{
		CharIDType charId = (*iter);
		uint32_t hp = GetPlayerLastHp(charId);
		Player *pPlayer = GetPlayer(charId);
		if (nullptr != pPlayer)
		{
			if ((uint32_t)pPlayer->GetAttr(C_HP) != hp)
			{
				UpdatePlayerHp(pPlayer);
				SetPlayerLastHp(charId, (uint32_t)pPlayer->GetAttr(C_HP));
			}
		}
	}
	
}

//是否是单人副本
bool Duplicate::IsSingleDup()
{
	return (EDuplicateKeyType_Single == m_paramEx.byKeyType);
}
//是否是多人副本
bool Duplicate::IsMulDup()
{
	if (IsRoomDup() || IsTeamDup())
	{
		return true;
	}
	return false;
}

//是否是房间副本
bool Duplicate::IsRoomDup()
{
	return (EDuplicateKeyType_Room == m_paramEx.byKeyType);
}

//是否是组队副本
bool Duplicate::IsTeamDup()
{
	return (EDuplicateKeyType_Team == m_paramEx.byKeyType);
}
//是否是云端试炼
bool Duplicate::IsCloud()
{
	if (EDuplicateKeyType_Union == m_paramEx.byKeyType)
	{
		if (EUnionSceneType_Cloud == m_paramEx.unionSceneType)
		{
			return true;
		}
	}
	return false;
}

//是否是竞技场副本
bool  Duplicate::IsArenaDup()
{
	if (EDuplicateKeyType_Arena == m_paramEx.byKeyType)
	{
		return true;
	}
	return false;
}

//是否是切磋副本
bool	Duplicate::IsCompeteDup()
{
	return EDuplicateKeyType_Compete == m_paramEx.byKeyType;
}

//是否是工会驻地
bool  Duplicate::IsUnionHomeDup()
{
	if (EDuplicateKeyType_Union == m_paramEx.byKeyType)
	{
		if (EUnionSceneType_Home == m_paramEx.unionSceneType)
		{
			return true;
		}
	}
	return false;
}
//是否是工会地宫
bool Duplicate::IsUnionDungeonDup()
{
	if (EDuplicateKeyType_Union == m_paramEx.byKeyType)
	{
		if (EUnionSceneType_DunGeon == m_paramEx.unionSceneType)
		{
			return true;
		}
	}
	return false;
}
//是否是瘟疫之战
bool Duplicate::IsPestilenceDup()
{
	if (EDuplicateKeyType_Pestilence == m_paramEx.byKeyType)
	{
		return true;
	}
	return false;
}

//是否是天梯
bool Duplicate::IsLadderDup()
{
	//天梯分到单人副本里面了，所以通过副本类型来区分
	if ((int8_t)EDuplicateType::EDuplicateType_Ladder == m_byType)
	{
		return true;
	}
	return false;
}

//初始化订阅事件
void Duplicate::InitCommonEvent()
{
	//订阅怪物进入场景事件
	if (!g_GetEvent()->Subscribe(this, EVENT_ENTER_SCENE, m_nSceneID, CREATURE_MONSTER, "Duplicate::Init"))
	{
		MMOLOG_FMT_ERROR("[logic] Duplicate::InitDuplicateEvent... subcribe monster enter scene event failed....duplicateid:%u ,mapid:%u , sceneid:%u ", m_nDuplicateID, m_nMapID, m_nSceneID);
	}
	//订阅所有怪物的死亡事件
	if (!g_GetEvent()->Subscribe(this, EVENT_CREATURE_DEAD, 0, CREATURE_MONSTER, "Duplicate::Init"))
	{
		MMOLOG_FMT_ERROR("[logic] Duplicate::InitDuplicateEvent... subcribe monster dead  event failed....duplicateid:%u ,mapid:%u , sceneid:%u ", m_nDuplicateID, m_nMapID, m_nSceneID);
	}
	
	//订阅NPC进入场景事件
	if (!g_GetEvent()->Subscribe(this, EVENT_ENTER_SCENE, m_nSceneID, CREATURE_NPC, "Duplicate::Init"))
	{
		MMOLOG_FMT_ERROR("[logic] Duplicate::InitDuplicateEvent... subcribe npc enter scene event failed....duplicateid:%u ,mapid:%u , sceneid:%u ", m_nDuplicateID, m_nMapID, m_nSceneID);
	}
	//订阅NPC死亡事件
	if (!g_GetEvent()->Subscribe(this, EVENT_CREATURE_DEAD, 0, CREATURE_NPC, "Duplicate::Init"))
	{
		MMOLOG_FMT_ERROR("[logic] Duplicate::InitDuplicateEvent... subcribe npc dead  event failed....duplicateid:%u ,mapid:%u , sceneid:%u ", m_nDuplicateID, m_nMapID, m_nSceneID);
	}

	//订阅机器人进入场景事件
	if (!g_GetEvent()->Subscribe(this, EVENT_ENTER_SCENE, m_nSceneID, CREATURE_REBOT, "Duplicate::Init"))
	{
		MMOLOG_FMT_ERROR("[logic] Duplicate::InitDuplicateEvent... subcribe rebot  enter scene event failed....duplicateid:%u ,mapid:%u , sceneid:%u ", m_nDuplicateID, m_nMapID, m_nSceneID);
	}

	//订阅角色进入场景事件
	if (!g_GetEvent()->Subscribe(this, EVENT_ENTER_SCENE, m_nSceneID, CREATURE_PLAYER, "Duplicate::Init"))
	{
		MMOLOG_FMT_ERROR("[logic] Duplicate::InitDuplicateEvent... subcribe player enter scene event failed....duplicateid:%u ,mapid:%u , sceneid:%u ", m_nDuplicateID, m_nMapID, m_nSceneID);
	}
	//订阅角色离开事件
	if (!g_GetEvent()->Subscribe(this, EVENT_LEAVE_SCENE, m_nSceneID, CREATURE_PLAYER, "Duplicate::Init"))
	{
		MMOLOG_FMT_ERROR("[logic] Duplicate::InitDuplicateEvent... subcribe player leave scene event failed....duplicateid:%u ,mapid:%u , sceneid:%u ", m_nDuplicateID, m_nMapID, m_nSceneID);
	}	
}

//角色进副本初始化订阅事件
void Duplicate::OnPlayerEnterEvent(CharIDType charId)
{
	//玩家杀怪事件可以通过怪物死亡事件参数中获得，这里不需要订阅
	/*//订阅角色杀怪事件
	if (!g_GetEvent()->Subscribe(this, EVENT_CREATURE_DEAD, charId, CREATURE_MONSTER, "Duplicate::CreatureEnter"))
	{
		LogErrFmtPrint("[logic] Duplicate::CreatureEnter....Subscribe player kill monster event failed....");
	}*/

	//订阅角色掉线事件
	if (!g_GetEvent()->Subscribe(this, EVENT_DISCONNECT, charId, CREATURE_PLAYER, "Duplicate::CreatureEnter"))
	{
		LogErrFmtPrint("[logic] Duplicate::CreatureEnter....Subscribe player disconnect event  failed....");
	}

	//订阅角色离开游戏
	if (!g_GetEvent()->Subscribe(this, EVENT_LOGINOUT_GAME, charId, CREATURE_PLAYER, "Duplicate::CreatureEnter"))
	{
		LogErrFmtPrint("[logic] Duplicate::CreatureEnter....Subscribe player logout game event  failed....");
	}


	//订阅角色自身死亡事件
	if (!g_GetEvent()->Subscribe(this, EVENT_CREATURE_DEAD, charId, CREATURE_PLAYER, "Duplicate::CreatureEnter"))
	{
		LogErrFmtPrint("[logic] Duplicate::CreatureEnter....Subscribe player dead event  failed....");
	}

	//订阅玩家使用物件事件
	if (!g_GetEvent()->Subscribe(this, EVENT_PLAYER_USE_MONSTER, charId, CREATURE_PLAYER, "Duplicate::CreatureEnter"))
	{
		LogErrFmtPrint("[logic] Duplicate::CreatureEnter....Subscribe player use thing event  failed....");
	}
	

	if (IsMulDup())
	{
		//订阅角色升级事件
		if (!g_GetEvent()->Subscribe(this, EVENT_LEVELUP, charId, CREATURE_PLAYER, "Duplicate::CreatureEnter"))
		{
			LogErrFmtPrint("[logic] Duplicate::CreatureEnter....Subscribe player level up  event  failed....");
		}
		//订阅角色外观改变事件
		if (!g_GetEvent()->Subscribe(this, EVENT_FACADE_CHANGE, charId, CREATURE_PLAYER, "Duplicate::CreatureEnter"))
		{
			LogErrFmtPrint("[logic] Duplicate::CreatureEnter....Subscribe player facade change  event  failed....");
		}
		//订阅角色受击事件
		if (!g_GetEvent()->Subscribe(this, EVENT_UNDER_ATTACK, charId, 0, "Duplicate::CreatureEnter"))
		{
			LogErrFmtPrint("[logic] Duplicate::CreatureEnter....Subscribe player under attack event  failed....");
		}
		//订阅角色攻击事件
		if (!g_GetEvent()->Subscribe(this, EVENT_ATTACK_SOMEBODY, charId, 0, "Duplicate::CreatureEnter"))
		{
			LogErrFmtPrint("[logic] Duplicate::CreatureEnter....Subscribe player attack sombody event  failed....");
		}


		//玩家信息广播需要放到最前面
		SET_UINT64::iterator iterUpdate = m_setPlayer.begin();
		for (; iterUpdate != m_setPlayer.end(); ++iterUpdate)
		{
			Player *pPlayer = GetPlayer((*iterUpdate));
			UpdatePlayerInfo(pPlayer);
		}

		SET_UINT64::iterator iterUpdateA = m_setPlayer.begin();
		for (; iterUpdateA != m_setPlayer.end(); ++iterUpdateA)
		{
			Player *pPlayer = GetPlayer((*iterUpdateA));
			UpdatePlayerFacade(pPlayer);
			UpdatePlayerLev(pPlayer);
			UpdatePlayerHp(pPlayer);
			UpdatePlayerOnline(pPlayer, 1);
			UpdatePlayerDie(pPlayer, 0);
		}
	}
	else if (IsPestilenceDup())
	{
		//订阅角色受击事件
		if (!g_GetEvent()->Subscribe(this, EVENT_UNDER_ATTACK, charId, 0, "Duplicate::CreatureEnter"))
		{
			LogErrFmtPrint("[logic] Duplicate::CreatureEnter....Subscribe player under attack event  failed....");
		}
	}
	else if (IsArenaDup())
	{
		//订阅机器人死亡事件
		if (!g_GetEvent()->Subscribe(this, EVENT_CREATURE_DEAD, 0, CREATURE_REBOT, "Duplicate::CreatureEnter"))
		{
			LogErrFmtPrint("[logic] Duplicate::CreatureEnter....Subscribe player kill rebot event failed....");
		}
	}
	if ((int8_t)EDuplicateType::EDuplicateType_Guide == GetType())
	{
		//新手引导副本需要订阅任务完成事件
		if (!g_GetEvent()->Subscribe(this, EVENT_FINISH_TASK, charId, CREATURE_PLAYER, "Duplicate::CreatureEnter"))
		{
			LogErrFmtPrint("[logic] Duplicate::CreatureEnter....Subscribe player finish task event failed....");
		}
	}


}

//角色离开取消订阅事件
void Duplicate::OnPlayerLeaveEvent(CharIDType charId)
{
	//取消订阅事件
	//g_GetEvent()->UnSubscribe(this, EVENT_CREATURE_DEAD, charId, CREATURE_MONSTER);
	g_GetEvent()->UnSubscribe(this, EVENT_DISCONNECT, charId, CREATURE_PLAYER);
	g_GetEvent()->UnSubscribe(this, EVENT_CREATURE_DEAD, charId, CREATURE_PLAYER);
	g_GetEvent()->UnSubscribe(this, EVENT_LOGINOUT_GAME, charId, CREATURE_PLAYER);
	g_GetEvent()->UnSubscribe(this, EVENT_PLAYER_USE_MONSTER, charId, CREATURE_PLAYER);
	

	if (IsMulDup())
	{
		g_GetEvent()->UnSubscribe(this, EVENT_LEVELUP, charId, CREATURE_PLAYER);
		g_GetEvent()->UnSubscribe(this, EVENT_FACADE_CHANGE, charId, CREATURE_PLAYER);
		g_GetEvent()->UnSubscribe(this, EVENT_UNDER_ATTACK, charId, 0);
		g_GetEvent()->UnSubscribe(this, EVENT_ATTACK_SOMEBODY, charId, 0);
	}
	else if (IsArenaDup())
	{
		g_GetEvent()->UnSubscribe(this, EVENT_CREATURE_DEAD, 0, CREATURE_REBOT);
	}
	else if (IsPestilenceDup())
	{
		g_GetEvent()->UnSubscribe(this, EVENT_UNDER_ATTACK, charId, 0);
	}

	if ((int8_t)EDuplicateType::EDuplicateType_Guide == GetType())
	{
		g_GetEvent()->UnSubscribe(this, EVENT_FINISH_TASK, charId, CREATURE_PLAYER);
	}
}

//通用的副本开始状态处理
void Duplicate::OnCommon_DupBeginState()
{
	//副本开始，延迟 2s 刷怪
	g_GetTimerAxis()->KillTimer(ETimer_StartBrush, this);
	g_GetTimerAxis()->SetTimer(ETimer_StartBrush, 2 * 1000, this, 1);
}

//通用副本完成的通知处理
void Duplicate::OnCommon_NotifyDupFinish(DuplicateResult &result)
{
	SET_UINT64 setPlayer = m_setPlayer;
	SET_UINT64::iterator iter = setPlayer.begin();
	for (; iter != setPlayer.end(); ++iter)
	{
		Player *pPlayer = GetPlayer((*iter));
		if (nullptr == pPlayer)
		{
			continue;
		}
		CharIDType cid = pPlayer->GetCid();
		OnNotifyFinish(cid, result);
		//
		Part *pPart = pPlayer->GetPart(PART_DUPLICATE);
		if (nullptr != pPart)
		{
			pPart->DuplicateFinish(result);
		}
	}

}

//通用的副本完成状态处理
void Duplicate::OnCommon_DupFinishState()
{
	//副本完成
	//结果（胜利，失败），死亡次数，杀怪数量，用时，评价
	uint64_t nSec = Time::Now().sec() - m_nStartTime;
	DuplicateResult result;
	result.nDuplicateID = m_nDuplicateID;
	result.nResult = m_nResult;
	result.byWinCamp = PestilenceWinCamp();
	result.byTeam = (m_paramEx.byKeyType == EDuplicateKeyType_Team) ? 1:0;

	LogDebugFmtPrint("[logic] OnCommon_DupFinishState....duplicateid:%u, dup_type:%d,  res:%d,sec:%llu ", m_nDuplicateID, m_byType, m_nResult, nSec);

	//通知副本完成
	OnCommon_NotifyDupFinish(result);
	//直接转到清理状态
	SetDuplicateState((int8_t)EDuplicateState::EDuplicateState_Clean);
}

//通用的副本翻牌状态处理
void Duplicate::OnCommon_DupFlopState()
{
	//设置抽奖时间 15s
	LogDebugFmtPrint("[logic] OnCommon_DupFlopState....duplicateid:%u, dup_type:%d  , sceneid:%u ", m_nDuplicateID,m_byType, m_nSceneID);
	g_GetTimerAxis()->KillTimer(ETimer_Flop, this);
	g_GetTimerAxis()->SetTimer(ETimer_Flop, 15 * 1000, this, 1);
}
//通用的翻牌状态 结束处理
void Duplicate::OnCommon_FlopStateEnd()
{
	//翻牌结束
	SET_UINT64 setPlayer = m_setPlayer;
	SET_UINT64::iterator iter = setPlayer.begin();
	if (iter != setPlayer.end())
	{
		Player *pPlayer = GetPlayer((*iter));
		if (nullptr != pPlayer)
		{
			Part *pPart = pPlayer->GetPart(PART_DUPLICATE);
			if (nullptr != pPart)
			{
			}
		}
	}

	SetDuplicateState((int8_t)EDuplicateState::EDuplicateState_Clean);
}
//通用的副本清理状态处理
void Duplicate::OnCommon_DupCleanState(uint32_t sec /*= DUP_CLEAN_STATE_SEC*/)
{
	_UNUSE(sec);
	g_GetTimerAxis()->KillTimer(ETimer_Flop, this);
	g_GetTimerAxis()->KillTimer(ETimer_Clean, this);
	//默认时间取副本配置里面的时间,同时服务端设置一个最大时间，避免因为策划配置错了，导致副本无法销毁
	int32_t secEx = m_pDuplicateCfg->endTimes + DUP_CLEAN_STATE_SEC;
	if (secEx <= 0)
	{
		secEx = DUP_CLEAN_STATE_SEC;
	}
	else if (secEx > DUP_CLEAN_STATE_MAX_SEC)
	{
		secEx = DUP_CLEAN_STATE_MAX_SEC;
	}
	
/*
	if (0 == sec || sec > DUP_CLEAN_STATE_SEC)
	{
		sec = DUP_CLEAN_STATE_SEC;
	}*/
	g_GetTimerAxis()->SetTimer(ETimer_Clean, secEx * 1000, this, 1);
}
//通用的清理状态 结束处理
void Duplicate::OnCommon_CleanStateEnd()
{
	//删除抽奖定时器
	g_GetTimerAxis()->KillTimer(ETimer_Flop, this);
	g_GetTimerAxis()->KillTimer(ETimer_Clean, this);
	//清理副本
	SET_UINT64 setPlayer = m_setPlayer;
	SET_UINT64::iterator iter = setPlayer.begin();
	for (; iter != setPlayer.end(); ++iter)
	{
		CharIDType cid = (*iter);
		Player *pPlayer = GetPlayer(cid);
		LogDebugFmtPrint("[logic] Duplicate::OnCommon_CleanStateEnd.... dupid:%u, sceneid:%u, mapid:%u, cid:%lu ", m_nDuplicateID, m_nSceneID, m_nMapID, cid);
		if (RET_SUCCESS != LeaveDuplicate(pPlayer))  // 当玩家离开场景之后，会转到 销毁状态
		{
			LogErrFmtPrint("[logic] OnCommon_DupClean....LeaveDuplicate failed....duplicateid:%u, dup_type:%d, cid%u", m_nDuplicateID, m_byType, cid);
		}
	}
}
//通用的副本销毁状态处理
void Duplicate::OnCommon_DupDestoryState(uint32_t sec/* = DUP_DESTORY_STATE_SEC*/)
{
	//销毁副本,这里确保能成功，先删除一次定时器
	g_GetTimerAxis()->KillTimer(ETimer_Flop, this);
	g_GetTimerAxis()->KillTimer(ETimer_Clean, this);
	g_GetTimerAxis()->KillTimer(ETimer_Destory, this);
	if (0 == sec || sec > DUP_DESTORY_STATE_SEC)
	{
		sec = DUP_DESTORY_STATE_SEC;
	}
	g_GetTimerAxis()->SetTimer(ETimer_Destory, sec * 1000, this, 1);
}

//通用的销毁状态 结束处理
void Duplicate::OnCommon_DestoryStateEnd()
{
	//回收
	g_GetDuplicateMgr()->RecycleDuplicate(this);
}

//通知所有怪物AI
void Duplicate::OnCommon_StopMonsterAi()
{
	SET_UINT64 setMonster = m_setMonster;
	SET_UINT64::iterator iter = setMonster.begin();
	for (; iter != setMonster.end(); ++iter)
	{
		uint64_t monsCid = (*iter);
		Monster *pMonster = GetMonster(monsCid);
		if (nullptr != pMonster)
		{
			CreatureCommonAI *pAi = pMonster->GetAiData();
			if (nullptr != pAi)
			{
				pAi->StopAI();
			}
		}
	}
}

//副本完成增加阵营声望
void Duplicate::OnCommon_AddPrestige()
{
	if (!IsMulDup() || RET_SUCCESS != m_nResult)
	{
		return;
	}
	//逐个比较队伍中的成员，比其他成员高出10级的
	MAP_UINT64_INT32 mapCharPrestige;
	mapCharPrestige.clear();
	SET_UINT64 setPlayer = m_setPlayer;
	SET_UINT64::iterator iter = setPlayer.begin();
	for (; iter != setPlayer.end(); ++iter)
	{
		CharIDType cid = (*iter);
		Player *pPlayer = GetPlayer(cid);
		if (nullptr == pPlayer)
		{
			continue;
		}
		int32_t campId = pPlayer->GetAttr(C_CAMP_ID);
		if (campId <= 0)
		{
			continue;
		}
		int32_t level = pPlayer->GetAttr(C_LEVEL);
		SET_UINT64::iterator iterEx = setPlayer.begin();
		for (; iterEx != setPlayer.end(); ++iterEx)
		{
			CharIDType compareCid = (*iterEx);
			if (cid == compareCid)
			{
				continue;
			}
			
			Player *pComparePlayer = GetPlayer(compareCid);
			if (nullptr == pComparePlayer)
			{
				continue;
			}
			int32_t compareCampId = pComparePlayer->GetAttr(C_CAMP_ID);
			if (compareCampId <= 0)
			{
				continue;
			}
			if (campId != compareCampId)
			{
				continue;
			}
			int32_t compareLevel = pComparePlayer->GetAttr(C_LEVEL);
			int32_t levelVal = level - compareLevel;
			//是否大于10级 CAMP_ADD_PRESTIGE_LEV_INTER
			if (levelVal >= CAMP_ADD_PRESTIGE_LEV_INTER)
			{
				MAP_UINT64_INT32::iterator iterChar = mapCharPrestige.find(cid);
				if (iterChar != mapCharPrestige.end())
				{
					iterChar->second += 1;
				}
				else
				{
					mapCharPrestige[cid] = 1;
				}
			}
		}
	}
	if (mapCharPrestige.size() > 0)
	{
		//通知中心服增加阵营声望
		g_GetPlayerMgr()->L2C_AddPrestige(mapCharPrestige);
	}
}

//通用的玩家离开副本处理
bool Duplicate::OnCommon_PlayerLeave(CharIDType cid,bool notify/* = true*/)
{
	//玩家离开，取消订阅事件
	OnPlayerLeaveEvent(cid);
	//
	Player *pPlayer = GetPlayer(cid);
	if (nullptr == pPlayer)
	{
		LogErrFmtPrint("[logic] Duplicate::OnCommon_PlayerLeave......nullptr == pPlayer.....dupid:%u,sceneid:%u cid:%lu ", m_nDuplicateID,m_nSceneID, cid);
		return false;
	}
	//
	if (nullptr != m_pCond)
	{
		m_pCond->onPlayerLeave(cid);
	}

	//离开副本的时候如果是死亡状态的话,离开之后需要复活下
	if (pPlayer->IsDead())
	{
		pPlayer->OnRevive(pPlayer->GetCid());
	}

	if (notify)
	{
		//通知part 部件离开
		Part *pPart = pPlayer->GetPart(PART_DUPLICATE);
		if (nullptr != pPart)
		{
			pPart->NotifyLeave(m_nDuplicateID, m_paramEx.byKeyType);
		}
		else
		{
			LogErrFmtPrint("[logic] Duplicate::OnCommon_PlayerLeave....player duplicate part is null ....duplicateid:%u, sceneid:%u , cid%lu ", m_nDuplicateID, m_nSceneID, cid);
		}
	}

	//删除角色死亡时间
	DelPlayerDieSec(cid);
	//删除角色
	DelPlayer(cid);
	//离开
	OnPlayerLeave(pPlayer);
	//返回中心服，玩家离开副本
	g_GetDuplicateMgr()->NotifyCenterLeaveDuplicate(m_nSceneID, cid);

	return true;
}

//初始化功勋
void Duplicate::InitExploit(CharIDType charId)
{
	m_mapExploit[charId] = 0;
}
//获取功勋
int32_t Duplicate::GetCharExploit(CharIDType charId)
{
	MAP_UINT64_INT32::iterator iter = m_mapExploit.find(charId);
	return (iter != m_mapExploit.end()) ? iter->second : 0;
}
//增加功勋
void Duplicate::AddExploit(CharIDType charId, int32_t exploit)
{
	MAP_UINT64_INT32::iterator iter = m_mapExploit.find(charId);
	if (iter != m_mapExploit.end())
	{
		iter->second += exploit;
		iter->second = (iter->second < 0) ? 0 : iter->second;

		Player *pPlayer = GetPlayer(charId);
		UpdatePlayerExploit(pPlayer, iter->second);
	}
}
//删除功勋
void Duplicate::DelExploit(CharIDType charId)
{
	m_mapExploit.erase(charId);
}

//设置活瘟疫之战动持续时间
void Duplicate::SetPestilenceContiSec(int32_t sec)
{
	if (nullptr != m_pCond)
	{
		m_pCond->setContiTime(sec);
	}
}

//获取瘟疫之战结果
int8_t Duplicate::PestilenceWinCamp()
{
	if (nullptr != m_pCond)
	{
		return m_pCond->winCamp();
	}
	return EDupCampType_None;
}

//是否需要复活
bool Duplicate::IsNeedRelive()
{
	//工会驻地，工会地宫，竞技场，天梯，瘟疫之战 不能复活的
	if (IsUnionHomeDup()
		|| IsUnionDungeonDup()
		|| IsArenaDup()
		|| IsLadderDup()
		|| IsPestilenceDup()
		|| IsCompeteDup()
		)
	{
		return false;
	}
	return true;
}

//获取进入副本参数
void Duplicate::GetEnterParam(DupEnterParam &enterParam)
{
	enterParam.dupId = m_nDuplicateID;
	enterParam.sceneId = m_nSceneID;
	enterParam.keyType = m_paramEx.byKeyType;
	enterParam.mapPlayerOutput = m_mapPlayerOuput;
	enterParam.mapPlayerBear = m_mapPlayerBear;
	enterParam.cloudEndTime = m_paramEx.endTime;
	//boss状态
	if (nullptr != m_pBrushMonster)
	{
		m_pBrushMonster->GetBossState(enterParam.mapBossState);
		m_pBrushMonster->GetCurWaveInfo(enterParam.curWave, enterParam.monsDie, enterParam.totalMons, enterParam.setBoss);
	}
	//怪物数量信息
	if (nullptr != m_pCond)
	{
		m_pCond->getMonsNum(enterParam.mapMonsDieNum, enterParam.mapMonsTotalNum);
	}
}

//检查怪物出生
void Duplicate::CheckMonsBorn()
{
	SET_UINT64::iterator iter = m_setBornMonster.begin();
	for (; iter != m_setBornMonster.end(); ++iter)
	{
		Monster *pMonster = GetMonster((*iter));
		if (nullptr != pMonster)
		{
			m_dupBlock.OnMonsBorn(pMonster->GetConfigId(), pMonster->GetFormationId());
			//记录怪物组
			AddMonsByGroup(pMonster->GetCid(), pMonster->GetFormationId());
		}
		else
		{
			LogErrFmtPrint("[logic] Duplicate::CheckMonsBorn....dupid:%u, sceneid:%u, cid:%lu ", m_nDuplicateID,m_nSceneID,(*iter));
		}
	}
	m_setBornMonster.clear();
}

//添加出生的怪物
void Duplicate::AddBornMonster(SET_UINT64 &setBorn)
{
	SET_UINT64::iterator iter = setBorn.begin();
	for (; iter != setBorn.end(); ++iter)
	{
		m_setBornMonster.insert((*iter));
	}	
}
//初始化所有类型怪物
void Duplicate::InitAllTypeMonster()
{
	//刷怪
	m_mapAllTypeMonster = m_brushCfg.mapTypeMonster;
	//场景怪
	SET_UINT64::iterator iter = m_setMonster.begin();
	for (; iter != m_setMonster.end(); ++iter)
	{
		Monster *pMonster = GetMonster((*iter));
		if (nullptr == pMonster)
		{
			continue;
		}
		int8_t parentType = (int8_t)pMonster->GetParentMonsterType();
		if (parentType <= 0)
		{
			continue;
		}
		MAP_INT8_MAP_UINT32_UINT32::iterator iterType = m_mapAllTypeMonster.find(parentType);
		if (iterType != m_mapAllTypeMonster.end())
		{
			MAP_UINT32_UINT32 &mapMonsNum = iterType->second;
			MAP_UINT32_UINT32::iterator iterMon = mapMonsNum.find(pMonster->GetConfigId());
			if (iterMon != mapMonsNum.end())
			{
				iterMon->second += 1;
			}
			else
			{
				mapMonsNum[pMonster->GetConfigId()] = 1;
			}
		}
		else
		{
			MAP_UINT32_UINT32 mapMonsNum;
			mapMonsNum.clear();
			mapMonsNum[pMonster->GetConfigId()] = 1;
			m_mapAllTypeMonster[parentType] = mapMonsNum;
		}
	}
	//统计所有怪物数量
	MAP_INT8_MAP_UINT32_UINT32::iterator iterNum = m_mapAllTypeMonster.begin();
	for (; iterNum != m_mapAllTypeMonster.end(); ++iterNum)
	{
		MAP_UINT32_UINT32 &mapMonster = iterNum->second;
		MAP_UINT32_UINT32::iterator iterMon = mapMonster.begin();
		for (; iterMon != mapMonster.end(); ++iterMon)
		{
			m_monsterNum += iterMon->second;
			//
			MAP_UINT32_INT32::iterator iterAll = m_mapAllMonster.find(iterMon->first);
			if (iterAll != m_mapAllMonster.end())
			{
				iterAll->second += iterMon->second;
			}
			else
			{
				m_mapAllMonster[iterMon->first] = iterMon->second;
			}
		}
	}
}

//获取类型怪数量
int32_t Duplicate::GetMonsNumByType(int8_t monsType)
{
	int32_t nNum = 0;
	MAP_INT8_MAP_UINT32_UINT32::iterator iterType = m_mapAllTypeMonster.find(monsType);
	if (iterType != m_mapAllTypeMonster.end())
	{
		MAP_UINT32_UINT32 &mapMonster = iterType->second;
		MAP_UINT32_UINT32::iterator iterMon = mapMonster.begin();
		for (; iterMon != mapMonster.end(); ++iterMon)
		{
			nNum += iterMon->second;
		}
	}
	return nNum;
}

//获取指定类型下指定怪物ID剩余数量
int32_t Duplicate::GetMonsNumByType(int8_t monsType, uint32_t monsterId)
{
	int32_t nNum = 0;
	MAP_INT8_MAP_UINT32_UINT32::iterator iterType = m_mapAllTypeMonster.find(monsType);
	if (iterType != m_mapAllTypeMonster.end())
	{
		MAP_UINT32_UINT32 &mapMonster = iterType->second;
		MAP_UINT32_UINT32::iterator iterMon = mapMonster.find(monsterId);
		if (iterMon != mapMonster.end())
		{
			nNum =  iterMon->second;
		}
	}
	return nNum;
}

//检查所有怪物是否有已经达到区域
void Duplicate::CheckEnterArea()
{
	if (nullptr == m_pCond)
	{
		return;
	}
	uint32_t areaId = m_pCond->transAreeId();
	if (areaId > 0)
	{
		SET_UINT64 setMonster = m_setMonster;
		SET_UINT64::iterator iter = setMonster.begin();
		for (; iter != setMonster.end(); ++iter)
		{
			uint64_t mon_cid = (*iter);
			Monster *pMonster = GetMonster(mon_cid);
			if (nullptr != pMonster)
			{
				Point3<float> pos = pMonster->GetPos();
				if (m_pScene->InArea(areaId, pos))
				{
					//怪物走到区域了，销毁怪物
					m_pCond->onTransNum(pMonster->GetConfigId(), 1, (int8_t)pMonster->GetParentMonsterType());
					int32_t hp = pMonster->GetAttr(C_HP);
					//设置怪物血量为0
					pMonster->AddAttr(C_HP, -hp, true);
				}
			}
		}
	}
}

//检查是否结束
int32_t Duplicate::CheckEnd()
{
	if (m_bEnd)
	{
		return -1;
	}
	if ((int8_t)EDuplicateState::EDuplicateState_Begin != GetDuplicateState())
	{
		return -1;
	}
	int32_t ret = -1;
	//条件更新
	m_pCond->condUpdate();
	//条件完成
	if (m_pCond->finishCond())
	{
		ret = m_pCond->result();
	}

	return ret;
}


//是否能进入
bool Duplicate::CanEnter(Creature *pCreature)
{
	if (nullptr == pCreature)
	{
		return true;
	}
	if (EDuplicateKeyType_Single == m_paramEx.byKeyType)
	{
		if ((uint64_t)pCreature->GetCid() != m_paramEx.keyValue)
		{
			return false;
		}
	}
	else if (EDuplicateKeyType_Team == m_paramEx.byKeyType)
	{
		if ((uint64_t)pCreature->GetAttr(C_TEAM_ID) != m_paramEx.keyValue)
		{
			return false;
		}
	}
	else if (EDuplicateKeyType_Room == m_paramEx.byKeyType)
	{
		if ((uint64_t)pCreature->GetAttr(C_ROOM_ID) != m_paramEx.keyValue)
		{
			return false;
		}
	}
	if (m_bEnd)
	{
		return false;
	}

	return OnCanEnter(pCreature);
}
//进入副本
bool Duplicate::EnterDuplicate(Creature *pCreature, Point3<float> &pos)
{
	if (nullptr == pCreature || nullptr == m_pScene)
	{
		LogErrFmtPrint("[logic] Duplicate::EnterDuplicate nullptr == pCreature || nullptr == m_pScene....");
		return false;
	}
	if (CREATURE_PLAYER != pCreature->CreatureKind())
	{
		//暂时只针对角色
		LogErrFmtPrint("[logic] Duplicate::EnterDuplicate....creature kind error ....cid:%u, kind:%d ,duplicateid:%u ",pCreature->GetCid(),pCreature->CreatureKind(),m_nDuplicateID );
		return false;
	}
	Player *pPlayer = dynamic_cast<Player*>(pCreature);
	if (nullptr == pPlayer)
	{
		LogErrFmtPrint("[logic] Duplicate::EnterDuplicate....creature kind error ....cid:%u, kind:%d ,duplicateid:%u ", pCreature->GetCid(), pCreature->CreatureKind(), m_nDuplicateID);
		return false;
	}
	if (!CanEnter(pCreature))
	{
		LogErrFmtPrint("[logic] Duplicate::EnterDuplicate....CanEnter failed....duplicateid:%u ,type:%d, cid:%u, teamid:%u , roomid:%u ", m_nDuplicateID, m_byType, pCreature->GetCid(), pCreature->GetAttr(C_TEAM_ID), pCreature->GetAttr(C_ROOM_ID));
		return false;
	}

	CharIDType cid = pPlayer->GetCid();
	if (nullptr != GetPlayer(cid))
	{
		LogErrFmtPrint("[logic] Duplicate::EnterDuplicate...player already in duplicate....cid:%u ", pCreature->GetCid());
		return false;
	}
	STransParam transParam;
	transParam.srcMapId = pPlayer->GetMapId();
	transParam.transType = ETransType_Dup;
	bool bret = pPlayer->TransScene(m_pScene->GetSceneId(), pos, m_pScene->GetMapId(), transParam);
	if (!bret)
	{
		LogErrFmtPrint("[logic] Duplicate::EnterDuplicate....pPlayer->TransScene failed...sceneID:%u,mapid:%u ", m_pScene->GetSceneId(), m_pScene->GetMapId());
	}
	return bret;
}

//是否能复活
bool Duplicate::CanRelive(CharIDType charId)
{
	if (!IsNeedRelive())
	{
		return false;
	}
	Player *pPlayer = GetPlayer(charId);
	if (nullptr == pPlayer)
	{
		return false;
	}
	if (GetPlayerDieSec(charId) <= 0)
	{
		//找不到复活倒计时
		return false;
	}
	return true;
}
//复活
bool Duplicate::Relive(Player *pPlayer)
{
	if (nullptr == pPlayer)
	{
		return false;
	}
	if (!pPlayer->IsDead())
	{
		return false;
	}
	CharIDType cid = pPlayer->GetCid();
	if (nullptr == GetPlayer(cid))
	{
		return false;
	}
	//附近复活点复活
	if (!pPlayer->OnNearBornRevive())
	{
		LogErrFmtPrint("[logic] Duplicate::Relive.....OnNearBornRevive failed...dupid:%u, sceneid:%u, mapid:%u, cid:%lu ",m_nDuplicateID,m_nSceneID,m_nMapID,cid);
		return false;
	}
	//多人副本 广播玩家复活状态
	if (IsMulDup())
	{
		UpdatePlayerDie(pPlayer, 0);
	}
	//删除玩家复活倒计时
	DelPlayerDieSec(cid);
	//增加复活次数
	AddPlayerReliveNum(cid);

	return true;
}
//复活（已废弃）
bool Duplicate::Relive(Player *pPlayer, int8_t byType)
{
	if (nullptr == pPlayer)
	{
		return false;
	}
	if (!pPlayer->IsDead())
	{
		return false;
	}
	CharIDType cid = pPlayer->GetCid();
	if (nullptr == GetPlayer(cid))
	{
		return false;
	}
	bool bFlag = true;
	if (byType == (int8_t)EDuplicateRelive::EDuplicateRelive_City)
	{
		//回城复活直接离开副本，不弹出结算界面,先复活
		pPlayer->OnRevive(cid);
		LogDebugFmtPrint("[logic] Duplicate::Relive...1111....dupid:%u, sceneid:%u, cid:%lu ", m_nDuplicateID, m_nSceneID, cid);
		if (RET_SUCCESS != LeaveDuplicate(pPlayer,true))
		{
			bFlag = false;
			LogErrFmtPrint("[logic] Duplicate::Relive....LeaveDuplicate failed...cid:%u ", cid);
		}
	}
	else
	{
		//原地复活
		pPlayer->OnRevive(cid);
		//复活需要通知前端
		if (IsMulDup())
		{
			UpdatePlayerDie(pPlayer, 0);
		}
	}
	if (bFlag)
	{
		//
		DelPlayerDieSec(cid);
		//记录玩家复活相关数据
		MAP_UINT64_UINT32::iterator iterRelive = m_mapReliveNum.find(cid);
		if (iterRelive != m_mapReliveNum.end())
		{
			iterRelive->second += 1;
		}
		else
		{
			m_mapReliveNum[cid] = 1;
		}

		OnRelive(pPlayer, byType);
	}

	return bFlag;
}

//离开副本
int32_t Duplicate::LeaveDuplicate(Player *pPlayer, bool retMainCity /*= false*/)
{
	if (nullptr == pPlayer)
	{
		LogErrFmtPrint("[logic] Duplicate::LeaveDuplicate nullptr == pPlayer....dupid:%u, seceneid:%u ",m_nDuplicateID,m_nSceneID);
		return RET_FAIL;
	}
	CharIDType cid = pPlayer->GetCid();
	if (nullptr == GetPlayer(cid))
	{
		LogErrFmtPrint("[logic] Duplicate::LeaveDuplicate can not find player...cid:%lu ", cid);
		return RET_DUPLICATE_NOT_IN_DUPLICATE;
	}
	uint32_t lastMapId = pPlayer->GetLastMapId();
	uint32_t lastSceneId = pPlayer->GetLastSceneId();
	Point3<float> lastPos = pPlayer->GetLastPos();
	//新手和剧情副本是区域出发进入的，需要设置离开副时的坐标,这里直接修改下进入副本前的坐标
	if ((int8_t)EDuplicateType::EDuplicateType_New == m_byType || (int8_t)EDuplicateType::EDuplicateType_Story == m_byType)
	{
		
		uint32_t areaId = GetBeforeArea(cid);
		const AreaAreaCfgInfo *pAreaCfg = g_GetAreaAreaCfgTable()->GetAreaAreaCfgInfo(areaId);
		if (nullptr != pAreaCfg)
		{
			if (pAreaCfg->belongToSceneID != (int32_t)lastMapId)
			{
				LogErrFmtPrint("[logic] Duplicate::LeaveDuplicate....pAreaCfg->belongToSceneID != lastMapId, areaid:%u,belongToSceneID:%u, lastmapid:%u, [%f,%f,%f] dupid:%u, sceneid:%u, mapid:%u, cid:%llu ", areaId, pAreaCfg->belongToSceneID,lastMapId,lastPos.x,lastPos.y,lastPos.z, m_nDuplicateID, m_nSceneID, m_nMapID, cid);
			}
			const AreaRefLocation *pAreaLoc = g_GetMapLocationCfg()->GetAreaRefLoc(pAreaCfg->belongToSceneID, areaId);
			if (nullptr != pAreaLoc)
			{
				const Point3<float> *ppos = pAreaLoc->flagPos();
				if (nullptr != ppos)
				{
					lastPos.x = ppos->x;
					lastPos.y = ppos->y;
					lastPos.z = ppos->z;
				}
				else
				{
					LogErrFmtPrint("[logic] Duplicate::LeaveDuplicate....nullptr == ppos, areaid:%u,belongToSceneID:%u, dupid:%u, sceneid:%u, mapid:%u, cid:%llu ", areaId, pAreaCfg->belongToSceneID, m_nDuplicateID, m_nSceneID, m_nMapID, cid);
				}
			}
			else
			{
				LogErrFmtPrint("[logic] Duplicate::LeaveDuplicate....nullptr == pAreaLoc, areaid:%u,belongToSceneID:%u, dupid:%u, sceneid:%u, mapid:%u, cid:%llu ", areaId, pAreaCfg->belongToSceneID, m_nDuplicateID, m_nSceneID, m_nMapID, cid);
			}
		}
		else
		{
			LogErrFmtPrint("[logic] Duplicate::LeaveDuplicate....nullptr == pAreaCfg, areaid:%u, dupid:%u, sceneid:%u, mapid:%u, cid:%llu ", areaId, m_nDuplicateID, m_nSceneID, m_nMapID, cid);
		}
	}
	if (retMainCity) //回到主城
	{
		
		/*bool bres = false;
		//如果当前等级小于等于 新手村地图，那么回城复活就回到新手村出生点
		//避免在新手副本中死亡，回到主城复活了
		if ((int8_t)EDuplicateType::EDuplicateType_New == m_byType)
		{
			const MapMapCfgInfo *pBornMapMapCfg = g_GetMapCfgMgr()->GetBornMapCfgInfo(pPlayer->GetAttr(C_PROF), pPlayer->GetAttr(C_GENDER));
			if (nullptr != pBornMapMapCfg)
			{
				if ((int32_t)pPlayer->GetAttr(C_LEVEL) <= pBornMapMapCfg->openLv)
				{
					const Point3<float> *pbornpos = g_GetMapCfgMgr()->RandBornPoint(pBornMapMapCfg->mapId);
					if (nullptr != pbornpos)
					{
						lastMapId = pBornMapMapCfg->mapId;
						lastSceneId = lastMapId;
						lastPos = *pbornpos;
						bres = true;
					}
					else
					{
						LogErrFmtPrint("[logic] Duplicate::LeaveDuplicate....nullptr == pbornpos, dupid:%u, sceneid:%u, mapid:%u, cid:%llu, bornmapid:%u ", m_nDuplicateID, m_nSceneID, m_nMapID, cid, pBornMapMapCfg->mapId);
					}
				}
			}
			else
			{
				LogErrFmtPrint("[logic] Duplicate::LeaveDuplicate....nullptr == pRoleBornCfg,  dupid:%u, sceneid:%u, mapid:%u, cid:%llu, prof:%d, sex:%d ", m_nDuplicateID, m_nSceneID, m_nMapID, cid, pPlayer->GetAttr(C_PROF), pPlayer->GetAttr(C_GENDER));
			}
		}	*/
		//新手副本回城复活 不会回到主城，直接在进入的区域点复活
		if ((int8_t)EDuplicateType::EDuplicateType_New != m_byType)
		{
			lastMapId = g_GetMapCfgMgr()->GetMainCityMapId();
			lastSceneId = lastMapId;
			lastPos = g_GetMapCfgMgr()->GetMainCityBornPos();
		}
	}

	//竞技场离开副本需要恢复玩家进副本之前的PK模式，
	//如果离开副本需要切换逻辑节点，需要在切换之前回复玩家PK模式，这里特殊处理下
	OnActiveBeforeLeave(cid);
	STransParam transParam;
	transParam.srcMapId = pPlayer->GetMapId();
	transParam.transType = ETransType_Dup;
	if (!pPlayer->TransScene(lastSceneId, lastPos, lastMapId, transParam))
	{
		OnActiveLeaveFaild(cid);
		LogErrFmtPrint("[logic] Duplicate::LeaveDuplicate ... player TransScene failed...cid:%llu, dupid:%u, sceneid:%u,mapid:%u, lastscene:%u,lastmap:%u, [%f,%f,%f], retmaincity:%d  ", cid,m_nDuplicateID,m_nSceneID,m_nMapID,lastSceneId,lastMapId,lastPos.x,lastPos.y,lastPos.z,(int32_t)retMainCity);
	}
	return RET_SUCCESS;

}
//刷怪完成
bool Duplicate::FinishBrush()
{
	return m_bFinishBrush;
}

//是否处于抽奖状态
bool Duplicate::IsFlopState()
{
	return GetDuplicateState() == (int8_t)EDuplicateState::EDuplicateState_Flop;
}

//是否结束
bool Duplicate::IsEnd()
{
	return m_bEnd;
}

//进入区域
bool Duplicate::EnterArea(uint32_t nAreaID)
{
	LogDebugFmtPrint("[logic] Duplicate::EnterArea....dupid:%u, sceneeid:%u ,nAreaID:%u ", m_nDuplicateID, m_nSceneID, nAreaID);
	if (nullptr == m_pBrushMonster)
	{
		return false;
	}
	//进入区域，阻挡处理
	m_dupBlock.OnEnterArea(nAreaID);
	//进入区域，刷怪处理
	bool ret = m_pBrushMonster->EnterAreaBrush(nAreaID);
	if (ret)
	{
		ret = OnEnterArea(nAreaID);
	}
	return ret;
}

//开始刷第几波怪物了
void Duplicate::StartBrushWave(int32_t wave)
{
	wave = wave;
	//通知客户端开始刷第几波怪物
}
//获取玩家复活次数
int32_t Duplicate::PlayerReliveNum(CharIDType cid)
{
	MAP_UINT64_UINT32::iterator iter = m_mapReliveNum.find(cid);
	return (iter != m_mapReliveNum.end()) ? iter->second : 0;
}
//玩家是否曾经进入副本
bool Duplicate::OnceEnter(CharIDType cid)
{
	SET_UINT64::iterator iter = m_setOnceEnter.find(cid);
	return (iter != m_setOnceEnter.end()) ? true : false;
}
//设置玩家是否可获得奖励
void Duplicate::SetCanReward(CharIDType cid, bool canReward)
{
	if (canReward)
	{
		m_setReward.insert(cid);
	}
	else
	{
		m_setReward.erase(cid);
	}
}
//获取玩家是否可获得奖励
bool Duplicate::CanReward(CharIDType cid)
{
	SET_UINT64::iterator iter = m_setReward.find(cid);
	return (iter != m_setReward.end()) ? true : false;
}

//初始化脚本
bool Duplicate::InitScript()
{
	if (nullptr == m_pBrushMonster)
	{
		LogErrFmtPrint("[logic] InitScript....nullptr == m_pBrushMonster....duplicateid:%u , mapid:%u, sceneid:%u ",m_nDuplicateID,m_nMapID,m_nSceneID);
		return false;
	}
	int8_t brushType = m_pBrushMonster->GetBrushType();
	if (!g_GetDuplicateMgr()->LoadLuaCfg(this,brushType,m_paramEx.step))
	{
		return false;
	}
	LogDebugFmtPrint("[logic] Duplicate::InitScript.... brushtype:%d , duplicateid:%u , mapid:%u, sceneid:%u ", brushType, m_nDuplicateID, m_nMapID, m_nSceneID);
	//
	if (!m_dupBlock.Init(this))
	{
		return false;
	}

	return true;
}


void Duplicate::OnDuplicateState_Ready()
{
	OnReady_State();
}

void Duplicate::OnDuplicateState_Begin()
{
	g_GetDuplicateMgr()->NotifyCenterDuplicateBegin(m_nSceneID);

	OnBegin_State();
}

void Duplicate::OnDuplicateState_Finish()
{
	//副本结束，停止怪物AI
	//OnCommon_StopMonsterAi();
	//增加阵营经验	判断
	OnCommon_AddPrestige();
	//副本完成
	OnFinish_State();
}

void Duplicate::OnDuplicateState_Flop()
{
	OnFlop_State();
}

void Duplicate::OnDuplicateState_Clean()
{
	OnClean_State();
}

void Duplicate::OnDuplicateState_Destory()
{
	//这里回收机器人和玩家镜像

	OnDestory_State();
}
